@lvce-editor/explorer-view 2.29.0 → 2.30.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 +139 -88
- package/package.json +1 -1
|
@@ -985,8 +985,8 @@ const getMissingIconRequests = (dirents, fileIconCache) => {
|
|
|
985
985
|
return missingRequests;
|
|
986
986
|
};
|
|
987
987
|
|
|
988
|
-
const getPath =
|
|
989
|
-
return
|
|
988
|
+
const getPath = item => {
|
|
989
|
+
return item.path;
|
|
990
990
|
};
|
|
991
991
|
|
|
992
992
|
const DELTA_EDITING = 100;
|
|
@@ -2968,23 +2968,41 @@ const handleDragOver = (state, x, y) => {
|
|
|
2968
2968
|
};
|
|
2969
2969
|
};
|
|
2970
2970
|
|
|
2971
|
-
const
|
|
2972
|
-
|
|
2973
|
-
return [];
|
|
2974
|
-
}
|
|
2975
|
-
return getChildDirents(pathSeparator, {
|
|
2976
|
-
depth: 0,
|
|
2977
|
-
path: root,
|
|
2978
|
-
type: Directory
|
|
2979
|
-
}, excluded);
|
|
2971
|
+
const isExpanded = item => {
|
|
2972
|
+
return item.type === DirectoryExpanded || item.type === DirectoryExpanding;
|
|
2980
2973
|
};
|
|
2981
2974
|
|
|
2982
|
-
const
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2975
|
+
const getExpandedDirents = items => {
|
|
2976
|
+
return items.filter(isExpanded);
|
|
2977
|
+
};
|
|
2978
|
+
|
|
2979
|
+
const getPaths = items => {
|
|
2980
|
+
return items.map(getPath);
|
|
2981
|
+
};
|
|
2982
|
+
|
|
2983
|
+
const refreshChildDirent = async (folder, dirent, pathSeparator, expandedFolders) => {
|
|
2984
|
+
const path = folder.path.endsWith(pathSeparator) ? `${folder.path}${dirent.name}` : `${folder.path}${pathSeparator}${dirent.name}`;
|
|
2985
|
+
const isExpandedFolder = expandedFolders.includes(path);
|
|
2986
|
+
const type = dirent.type === 'directory' ? isExpandedFolder ? DirectoryExpanded : Directory : File;
|
|
2987
|
+
const item = {
|
|
2988
|
+
name: dirent.name,
|
|
2989
|
+
type,
|
|
2990
|
+
path,
|
|
2991
|
+
depth: folder.depth + 1,
|
|
2992
|
+
selected: false
|
|
2993
|
+
};
|
|
2994
|
+
if (isExpandedFolder) {
|
|
2995
|
+
const nestedItems = await refreshChildDirents(item, pathSeparator, expandedFolders);
|
|
2996
|
+
return [item, ...nestedItems];
|
|
2986
2997
|
}
|
|
2987
|
-
return
|
|
2998
|
+
return [item];
|
|
2999
|
+
};
|
|
3000
|
+
const refreshChildDirents = async (folder, pathSeparator, expandedFolders) => {
|
|
3001
|
+
const childDirents = await readDirWithFileTypes(folder.path);
|
|
3002
|
+
const childItems = await Promise.all(childDirents.map(async dirent => {
|
|
3003
|
+
return refreshChildDirent(folder, dirent, pathSeparator, expandedFolders);
|
|
3004
|
+
}));
|
|
3005
|
+
return childItems.flat();
|
|
2988
3006
|
};
|
|
2989
3007
|
|
|
2990
3008
|
// TODO add lots of tests for this
|
|
@@ -2995,24 +3013,73 @@ const refresh = async state => {
|
|
|
2995
3013
|
minLineY,
|
|
2996
3014
|
height,
|
|
2997
3015
|
itemHeight,
|
|
2998
|
-
fileIconCache
|
|
3016
|
+
fileIconCache,
|
|
3017
|
+
items,
|
|
3018
|
+
focusedIndex
|
|
2999
3019
|
} = state;
|
|
3000
|
-
|
|
3001
|
-
|
|
3020
|
+
|
|
3021
|
+
// Get all expanded folders
|
|
3022
|
+
const expandedDirents = getExpandedDirents(items);
|
|
3023
|
+
const expandedFolders = getPaths(expandedDirents);
|
|
3024
|
+
|
|
3025
|
+
// Get top level dirents
|
|
3026
|
+
const topLevelDirents = await readDirWithFileTypes(root);
|
|
3027
|
+
const newDirents = topLevelDirents.map(dirent => ({
|
|
3028
|
+
name: dirent.name,
|
|
3029
|
+
type: dirent.type === 'directory' ? Directory : File,
|
|
3030
|
+
path: root.endsWith(pathSeparator) ? `${root}${dirent.name}` : `${root}${pathSeparator}${dirent.name}`,
|
|
3031
|
+
depth: 0,
|
|
3032
|
+
selected: false
|
|
3033
|
+
}));
|
|
3034
|
+
|
|
3035
|
+
// Process expanded folders in parallel
|
|
3036
|
+
const expandedFolderResults = await Promise.all(expandedFolders.map(async folderPath => {
|
|
3037
|
+
const folderIndex = newDirents.findIndex(item => item.path === folderPath);
|
|
3038
|
+
if (folderIndex !== -1) {
|
|
3039
|
+
const folder = newDirents[folderIndex];
|
|
3040
|
+
if (folder.type === Directory) {
|
|
3041
|
+
const childItems = await refreshChildDirents(folder, pathSeparator, expandedFolders);
|
|
3042
|
+
// @ts-ignore
|
|
3043
|
+
folder.type = DirectoryExpanded;
|
|
3044
|
+
return {
|
|
3045
|
+
folderIndex,
|
|
3046
|
+
childItems
|
|
3047
|
+
};
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
3050
|
+
return null;
|
|
3051
|
+
}));
|
|
3052
|
+
|
|
3053
|
+
// Insert child items in the correct order
|
|
3054
|
+
let offset = 0;
|
|
3055
|
+
for (const result of expandedFolderResults) {
|
|
3056
|
+
if (result) {
|
|
3057
|
+
const {
|
|
3058
|
+
folderIndex,
|
|
3059
|
+
childItems
|
|
3060
|
+
} = result;
|
|
3061
|
+
newDirents.splice(folderIndex + 1 + offset, 0, ...childItems);
|
|
3062
|
+
offset += childItems.length;
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3002
3065
|
const maxLineY = getExplorerMaxLineY(minLineY, height, itemHeight, newDirents.length);
|
|
3003
3066
|
const visible = newDirents.slice(minLineY, maxLineY);
|
|
3004
3067
|
const {
|
|
3005
3068
|
icons,
|
|
3006
3069
|
newFileIconCache
|
|
3007
3070
|
} = await getFileIcons(visible, fileIconCache);
|
|
3008
|
-
|
|
3071
|
+
let newFocusedIndex = focusedIndex;
|
|
3072
|
+
if (focusedIndex >= newDirents.length) {
|
|
3073
|
+
newFocusedIndex = newDirents.length - 1;
|
|
3074
|
+
}
|
|
3075
|
+
return {
|
|
3009
3076
|
...state,
|
|
3010
3077
|
items: newDirents,
|
|
3011
3078
|
fileIconCache: newFileIconCache,
|
|
3012
3079
|
icons,
|
|
3013
|
-
maxLineY
|
|
3080
|
+
maxLineY,
|
|
3081
|
+
focusedIndex: newFocusedIndex
|
|
3014
3082
|
};
|
|
3015
|
-
return state3;
|
|
3016
3083
|
};
|
|
3017
3084
|
|
|
3018
3085
|
const applyOperation = operation => {
|
|
@@ -3109,7 +3176,7 @@ const uploadFileSystemHandles = async (root, pathSeparator, fileSystemHandles) =
|
|
|
3109
3176
|
return true;
|
|
3110
3177
|
};
|
|
3111
3178
|
|
|
3112
|
-
const mergeDirents$
|
|
3179
|
+
const mergeDirents$2 = (oldDirents, newDirents) => {
|
|
3113
3180
|
return newDirents;
|
|
3114
3181
|
};
|
|
3115
3182
|
const getMergedDirents$2 = async (root, pathSeparator, dirents) => {
|
|
@@ -3117,7 +3184,7 @@ const getMergedDirents$2 = async (root, pathSeparator, dirents) => {
|
|
|
3117
3184
|
path: root,
|
|
3118
3185
|
depth: 0
|
|
3119
3186
|
});
|
|
3120
|
-
const mergedDirents = mergeDirents$
|
|
3187
|
+
const mergedDirents = mergeDirents$2(dirents, childDirents);
|
|
3121
3188
|
return mergedDirents;
|
|
3122
3189
|
};
|
|
3123
3190
|
const handleDrop$2 = async (state, fileHandles, files) => {
|
|
@@ -3166,7 +3233,7 @@ const copyFilesElectron = async (root, pathSeparator, fileHandles, files, paths)
|
|
|
3166
3233
|
await applyFileOperations(operations);
|
|
3167
3234
|
};
|
|
3168
3235
|
|
|
3169
|
-
const mergeDirents = (oldDirents, newDirents) => {
|
|
3236
|
+
const mergeDirents$1 = (oldDirents, newDirents) => {
|
|
3170
3237
|
return newDirents;
|
|
3171
3238
|
};
|
|
3172
3239
|
const getMergedDirents$1 = async (root, pathSeparator, dirents) => {
|
|
@@ -3174,7 +3241,7 @@ const getMergedDirents$1 = async (root, pathSeparator, dirents) => {
|
|
|
3174
3241
|
path: root,
|
|
3175
3242
|
depth: 0
|
|
3176
3243
|
});
|
|
3177
|
-
const mergedDirents = mergeDirents(dirents, childDirents);
|
|
3244
|
+
const mergedDirents = mergeDirents$1(dirents, childDirents);
|
|
3178
3245
|
return mergedDirents;
|
|
3179
3246
|
};
|
|
3180
3247
|
const handleDrop$1 = async (state, fileHandles, files, paths) => {
|
|
@@ -3427,6 +3494,25 @@ const handleKeyDown = (state, key) => {
|
|
|
3427
3494
|
};
|
|
3428
3495
|
};
|
|
3429
3496
|
|
|
3497
|
+
const getTopLevelDirents = (root, pathSeparator, excluded) => {
|
|
3498
|
+
if (!root) {
|
|
3499
|
+
return [];
|
|
3500
|
+
}
|
|
3501
|
+
return getChildDirents(pathSeparator, {
|
|
3502
|
+
depth: 0,
|
|
3503
|
+
path: root,
|
|
3504
|
+
type: Directory
|
|
3505
|
+
}, excluded);
|
|
3506
|
+
};
|
|
3507
|
+
|
|
3508
|
+
const mergeDirents = (oldDirents, newDirents) => {
|
|
3509
|
+
const merged = [];
|
|
3510
|
+
for (const newDirent of newDirents) {
|
|
3511
|
+
merged.push(newDirent);
|
|
3512
|
+
}
|
|
3513
|
+
return merged;
|
|
3514
|
+
};
|
|
3515
|
+
|
|
3430
3516
|
// TODO add lots of tests for this
|
|
3431
3517
|
const updateRoot = async state1 => {
|
|
3432
3518
|
// @ts-ignore
|
|
@@ -3441,7 +3527,7 @@ const updateRoot = async state1 => {
|
|
|
3441
3527
|
// if (state2.disposed || state2.root !== state1.root) {
|
|
3442
3528
|
// return state2
|
|
3443
3529
|
// }
|
|
3444
|
-
const newDirents = mergeDirents
|
|
3530
|
+
const newDirents = mergeDirents(state1.items, topLevelDirents);
|
|
3445
3531
|
const state3 = {
|
|
3446
3532
|
...state1,
|
|
3447
3533
|
items: newDirents
|
|
@@ -3929,70 +4015,35 @@ const openContainingFolder = async state => {
|
|
|
3929
4015
|
return state;
|
|
3930
4016
|
};
|
|
3931
4017
|
|
|
3932
|
-
|
|
3933
|
-
const
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
await remove(absolutePath);
|
|
3945
|
-
} catch {
|
|
3946
|
-
// TODO vscode shows error as alert (no stacktrace) and retry button
|
|
3947
|
-
// maybe should show alert as well, but where to put stacktrace?
|
|
3948
|
-
// on web should probably show notification (dialog)
|
|
3949
|
-
// ErrorHandling.handleError(error)
|
|
3950
|
-
// await ErrorHandling.showErrorDialog(error)
|
|
3951
|
-
return state;
|
|
3952
|
-
}
|
|
3953
|
-
// TODO avoid state mutation
|
|
3954
|
-
// @ts-ignore
|
|
3955
|
-
const newVersion = ++state.version;
|
|
3956
|
-
// TODO race condition
|
|
3957
|
-
// const newState = await loadContent(state:any)
|
|
3958
|
-
// @ts-ignore
|
|
3959
|
-
if (state.version !== newVersion || state.disposed) {
|
|
3960
|
-
return state;
|
|
3961
|
-
}
|
|
3962
|
-
// TODO is it possible to make this more functional instead of mutating state?
|
|
3963
|
-
// maybe every function returns a new state?
|
|
3964
|
-
const index = state.items.indexOf(dirent);
|
|
3965
|
-
let deleteEnd = index + 1;
|
|
3966
|
-
for (; deleteEnd < state.items.length; deleteEnd++) {
|
|
3967
|
-
if (state.items[deleteEnd].depth <= dirent.depth) {
|
|
3968
|
-
break;
|
|
4018
|
+
const getSelectedItems = (items, focusedIndex) => {
|
|
4019
|
+
const dirent = items[focusedIndex];
|
|
4020
|
+
const selectedItems = items.filter(item => item.selected || item === dirent);
|
|
4021
|
+
return selectedItems;
|
|
4022
|
+
};
|
|
4023
|
+
|
|
4024
|
+
const removePaths = async paths => {
|
|
4025
|
+
for (const item of paths) {
|
|
4026
|
+
try {
|
|
4027
|
+
await remove(item);
|
|
4028
|
+
} catch {
|
|
4029
|
+
// ignore
|
|
3969
4030
|
}
|
|
3970
4031
|
}
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
let indexToFocus = -1;
|
|
3975
|
-
if (newDirents.length === 0) {
|
|
3976
|
-
indexToFocus = -1;
|
|
3977
|
-
} else if (index < state.focusedIndex) {
|
|
3978
|
-
indexToFocus = state.focusedIndex - 1;
|
|
3979
|
-
} else if (index === state.focusedIndex) {
|
|
3980
|
-
indexToFocus = Math.max(state.focusedIndex - 1, 0);
|
|
3981
|
-
} else {
|
|
3982
|
-
indexToFocus = Math.max(state.focusedIndex - 1, 0);
|
|
3983
|
-
}
|
|
3984
|
-
const visible = newDirents.slice(state.minLineY, state.maxLineY);
|
|
4032
|
+
};
|
|
4033
|
+
|
|
4034
|
+
const removeDirent = async state => {
|
|
3985
4035
|
const {
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
} =
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
4036
|
+
items,
|
|
4037
|
+
focusedIndex
|
|
4038
|
+
} = state;
|
|
4039
|
+
const selectedItems = getSelectedItems(items, focusedIndex);
|
|
4040
|
+
if (selectedItems.length === 0) {
|
|
4041
|
+
return state;
|
|
4042
|
+
}
|
|
4043
|
+
const toRemove = getPaths(selectedItems);
|
|
4044
|
+
await removePaths(toRemove);
|
|
4045
|
+
const newState = await refresh(state);
|
|
4046
|
+
return newState;
|
|
3996
4047
|
};
|
|
3997
4048
|
|
|
3998
4049
|
const getNewDirentsForRename = (items, focusedIndex) => {
|