@lvce-editor/explorer-view 2.28.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 +244 -93
- 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;
|
|
@@ -1474,6 +1474,13 @@ const cancelEdit = state => {
|
|
|
1474
1474
|
};
|
|
1475
1475
|
};
|
|
1476
1476
|
|
|
1477
|
+
const cancelTypeAhead = state => {
|
|
1478
|
+
return {
|
|
1479
|
+
...state,
|
|
1480
|
+
focusWord: ''
|
|
1481
|
+
};
|
|
1482
|
+
};
|
|
1483
|
+
|
|
1477
1484
|
const isTopLevel$1 = dirent => {
|
|
1478
1485
|
return dirent.depth === 1;
|
|
1479
1486
|
};
|
|
@@ -1580,6 +1587,20 @@ const create$1 = () => {
|
|
|
1580
1587
|
};
|
|
1581
1588
|
};
|
|
1582
1589
|
return wrapped;
|
|
1590
|
+
},
|
|
1591
|
+
diff(uid, modules, numbers) {
|
|
1592
|
+
const {
|
|
1593
|
+
oldState,
|
|
1594
|
+
newState
|
|
1595
|
+
} = states[uid];
|
|
1596
|
+
const diffResult = [];
|
|
1597
|
+
for (let i = 0; i < modules.length; i++) {
|
|
1598
|
+
const fn = modules[i];
|
|
1599
|
+
if (!fn(oldState, newState)) {
|
|
1600
|
+
diffResult.push(numbers[i]);
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
return diffResult;
|
|
1583
1604
|
}
|
|
1584
1605
|
};
|
|
1585
1606
|
};
|
|
@@ -1630,7 +1651,9 @@ const create2 = (uid, uri, x, y, width, height, args, parentUid, platform = 0) =
|
|
|
1630
1651
|
editingSelection: {
|
|
1631
1652
|
start: 0,
|
|
1632
1653
|
end: 0
|
|
1633
|
-
}
|
|
1654
|
+
},
|
|
1655
|
+
focusWord: '',
|
|
1656
|
+
focusWordTimeout: 800
|
|
1634
1657
|
};
|
|
1635
1658
|
set(uid, state, state);
|
|
1636
1659
|
};
|
|
@@ -1671,7 +1694,9 @@ const create = (id, uri, x, y, width, height, args, parentUid, platform = 0) =>
|
|
|
1671
1694
|
editingSelection: {
|
|
1672
1695
|
start: 0,
|
|
1673
1696
|
end: 0
|
|
1674
|
-
}
|
|
1697
|
+
},
|
|
1698
|
+
focusWord: '',
|
|
1699
|
+
focusWordTimeout: 800
|
|
1675
1700
|
};
|
|
1676
1701
|
set(state.uid, state, state);
|
|
1677
1702
|
return state;
|
|
@@ -1999,7 +2024,7 @@ const focusIndex = (state, index) => {
|
|
|
1999
2024
|
} = state;
|
|
2000
2025
|
const newItems = items.map((item, i) => ({
|
|
2001
2026
|
...item,
|
|
2002
|
-
selected: i === index ?
|
|
2027
|
+
selected: i === index ? false : false
|
|
2003
2028
|
}));
|
|
2004
2029
|
if (index < minLineY) {
|
|
2005
2030
|
if (index < 0) {
|
|
@@ -2112,7 +2137,7 @@ const focusPrevious = state => {
|
|
|
2112
2137
|
}
|
|
2113
2138
|
};
|
|
2114
2139
|
|
|
2115
|
-
const commandIds = ['acceptEdit', 'cancelEdit', 'collapseAll', 'copyPath', 'copyRelativePath', 'dispose', 'expandAll', 'expandRecursively', 'focus', 'focusFirst', 'focusIndex', 'focusLast', 'focusNext', 'focusNone', 'focusPrevious', 'getFocusedDirent', 'getMenuEntries2', 'getMouseActions', 'handleArrowLeft', 'handleArrowLeft', 'handleArrowRight', 'handleArrowRight', 'handleBlur', 'handleClick', 'handleClickAt', 'handleClickCurrent', 'handleClickCurrentButKeepFocus', 'handleClickOpenFolder', 'handleContextMenu', 'handleContextMenuKeyboard', 'handleCopy', 'handleDragLeave', 'handleDragOver', 'handleDrop', 'handleFocus', 'handleIconThemeChange', 'handleInputBlur', 'handleInputClick', 'handleLanguagesChanged', 'handleMouseEnter', 'handleMouseLeave', 'handlePaste', 'handlePointerDown', 'handleUpload', 'handleWheel', 'handleWorkspaceChange', 'hotReload', 'newFile', 'newFolder', 'openContainingFolder', 'refresh', 'removeDirent', 'rename', 'renameDirent', 'renderEventListeners', 'revealItem', 'revealItem', 'scrollDown', 'scrollUp', 'selectAll', 'selectDown', 'selectUp', 'setDeltaY', 'setSelectedIndices', 'updateEditingValue', 'updateIcons'];
|
|
2140
|
+
const commandIds = ['acceptEdit', 'cancelEdit', 'collapseAll', 'copyPath', 'copyRelativePath', 'dispose', 'expandAll', 'expandRecursively', 'focus', 'focusFirst', 'focusIndex', 'focusLast', 'focusNext', 'focusNone', 'focusPrevious', 'getFocusedDirent', 'getMenuEntries2', 'getMouseActions', 'handleArrowLeft', 'handleArrowLeft', 'handleArrowRight', 'handleArrowRight', 'handleBlur', 'handleClick', 'handleClickAt', 'handleClickCurrent', 'handleClickCurrentButKeepFocus', 'handleClickOpenFolder', 'handleContextMenu', 'handleContextMenuKeyboard', 'handleCopy', 'handleDragLeave', 'handleDragOver', 'handleDrop', 'handleFocus', 'handleIconThemeChange', 'handleInputBlur', 'handleInputClick', 'handleLanguagesChanged', 'handleMouseEnter', 'handleMouseLeave', 'handlePaste', 'handlePointerDown', 'handleUpload', 'handleWheel', 'handleWorkspaceChange', 'hotReload', 'newFile', 'newFolder', 'openContainingFolder', 'refresh', 'removeDirent', 'rename', 'renameDirent', 'renderEventListeners', 'revealItem', 'revealItem', 'scrollDown', 'scrollUp', 'selectAll', 'selectDown', 'selectUp', 'setDeltaY', 'setSelectedIndices', 'cancelTypeAhead', 'updateEditingValue', 'handleKeyDown', 'updateIcons'];
|
|
2116
2141
|
|
|
2117
2142
|
const getCommandIds = () => {
|
|
2118
2143
|
return commandIds;
|
|
@@ -2943,23 +2968,41 @@ const handleDragOver = (state, x, y) => {
|
|
|
2943
2968
|
};
|
|
2944
2969
|
};
|
|
2945
2970
|
|
|
2946
|
-
const
|
|
2947
|
-
|
|
2948
|
-
return [];
|
|
2949
|
-
}
|
|
2950
|
-
return getChildDirents(pathSeparator, {
|
|
2951
|
-
depth: 0,
|
|
2952
|
-
path: root,
|
|
2953
|
-
type: Directory
|
|
2954
|
-
}, excluded);
|
|
2971
|
+
const isExpanded = item => {
|
|
2972
|
+
return item.type === DirectoryExpanded || item.type === DirectoryExpanding;
|
|
2955
2973
|
};
|
|
2956
2974
|
|
|
2957
|
-
const
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
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];
|
|
2961
2997
|
}
|
|
2962
|
-
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();
|
|
2963
3006
|
};
|
|
2964
3007
|
|
|
2965
3008
|
// TODO add lots of tests for this
|
|
@@ -2970,24 +3013,73 @@ const refresh = async state => {
|
|
|
2970
3013
|
minLineY,
|
|
2971
3014
|
height,
|
|
2972
3015
|
itemHeight,
|
|
2973
|
-
fileIconCache
|
|
3016
|
+
fileIconCache,
|
|
3017
|
+
items,
|
|
3018
|
+
focusedIndex
|
|
2974
3019
|
} = state;
|
|
2975
|
-
|
|
2976
|
-
|
|
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
|
+
}
|
|
2977
3065
|
const maxLineY = getExplorerMaxLineY(minLineY, height, itemHeight, newDirents.length);
|
|
2978
3066
|
const visible = newDirents.slice(minLineY, maxLineY);
|
|
2979
3067
|
const {
|
|
2980
3068
|
icons,
|
|
2981
3069
|
newFileIconCache
|
|
2982
3070
|
} = await getFileIcons(visible, fileIconCache);
|
|
2983
|
-
|
|
3071
|
+
let newFocusedIndex = focusedIndex;
|
|
3072
|
+
if (focusedIndex >= newDirents.length) {
|
|
3073
|
+
newFocusedIndex = newDirents.length - 1;
|
|
3074
|
+
}
|
|
3075
|
+
return {
|
|
2984
3076
|
...state,
|
|
2985
3077
|
items: newDirents,
|
|
2986
3078
|
fileIconCache: newFileIconCache,
|
|
2987
3079
|
icons,
|
|
2988
|
-
maxLineY
|
|
3080
|
+
maxLineY,
|
|
3081
|
+
focusedIndex: newFocusedIndex
|
|
2989
3082
|
};
|
|
2990
|
-
return state3;
|
|
2991
3083
|
};
|
|
2992
3084
|
|
|
2993
3085
|
const applyOperation = operation => {
|
|
@@ -3084,7 +3176,7 @@ const uploadFileSystemHandles = async (root, pathSeparator, fileSystemHandles) =
|
|
|
3084
3176
|
return true;
|
|
3085
3177
|
};
|
|
3086
3178
|
|
|
3087
|
-
const mergeDirents$
|
|
3179
|
+
const mergeDirents$2 = (oldDirents, newDirents) => {
|
|
3088
3180
|
return newDirents;
|
|
3089
3181
|
};
|
|
3090
3182
|
const getMergedDirents$2 = async (root, pathSeparator, dirents) => {
|
|
@@ -3092,7 +3184,7 @@ const getMergedDirents$2 = async (root, pathSeparator, dirents) => {
|
|
|
3092
3184
|
path: root,
|
|
3093
3185
|
depth: 0
|
|
3094
3186
|
});
|
|
3095
|
-
const mergedDirents = mergeDirents$
|
|
3187
|
+
const mergedDirents = mergeDirents$2(dirents, childDirents);
|
|
3096
3188
|
return mergedDirents;
|
|
3097
3189
|
};
|
|
3098
3190
|
const handleDrop$2 = async (state, fileHandles, files) => {
|
|
@@ -3141,7 +3233,7 @@ const copyFilesElectron = async (root, pathSeparator, fileHandles, files, paths)
|
|
|
3141
3233
|
await applyFileOperations(operations);
|
|
3142
3234
|
};
|
|
3143
3235
|
|
|
3144
|
-
const mergeDirents = (oldDirents, newDirents) => {
|
|
3236
|
+
const mergeDirents$1 = (oldDirents, newDirents) => {
|
|
3145
3237
|
return newDirents;
|
|
3146
3238
|
};
|
|
3147
3239
|
const getMergedDirents$1 = async (root, pathSeparator, dirents) => {
|
|
@@ -3149,7 +3241,7 @@ const getMergedDirents$1 = async (root, pathSeparator, dirents) => {
|
|
|
3149
3241
|
path: root,
|
|
3150
3242
|
depth: 0
|
|
3151
3243
|
});
|
|
3152
|
-
const mergedDirents = mergeDirents(dirents, childDirents);
|
|
3244
|
+
const mergedDirents = mergeDirents$1(dirents, childDirents);
|
|
3153
3245
|
return mergedDirents;
|
|
3154
3246
|
};
|
|
3155
3247
|
const handleDrop$1 = async (state, fileHandles, files, paths) => {
|
|
@@ -3335,6 +3427,92 @@ const handleInputClick = state => {
|
|
|
3335
3427
|
return state;
|
|
3336
3428
|
};
|
|
3337
3429
|
|
|
3430
|
+
const filterByFocusWord = (items, focusedIndex, focusWord) => {
|
|
3431
|
+
if (items.length === 0) {
|
|
3432
|
+
return -1;
|
|
3433
|
+
}
|
|
3434
|
+
const matches = [];
|
|
3435
|
+
for (let i = 0; i < items.length; i++) {
|
|
3436
|
+
if (items[i].toLowerCase().includes(focusWord)) {
|
|
3437
|
+
matches.push(i);
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
if (matches.length === 0) {
|
|
3441
|
+
return -1;
|
|
3442
|
+
}
|
|
3443
|
+
|
|
3444
|
+
// Find the next match after the current focus
|
|
3445
|
+
let nextIndex = matches.findIndex(index => index > focusedIndex);
|
|
3446
|
+
if (nextIndex === -1) {
|
|
3447
|
+
// If no match found after current focus, wrap around to the first match
|
|
3448
|
+
nextIndex = 0;
|
|
3449
|
+
}
|
|
3450
|
+
return matches[nextIndex];
|
|
3451
|
+
};
|
|
3452
|
+
|
|
3453
|
+
const RE_ASCII = /^[a-z]$/;
|
|
3454
|
+
const isAscii = key => {
|
|
3455
|
+
return RE_ASCII.test(key);
|
|
3456
|
+
};
|
|
3457
|
+
|
|
3458
|
+
let timeout;
|
|
3459
|
+
const handleKeyDown = (state, key) => {
|
|
3460
|
+
const {
|
|
3461
|
+
focusWord,
|
|
3462
|
+
items,
|
|
3463
|
+
focusedIndex,
|
|
3464
|
+
focusWordTimeout
|
|
3465
|
+
} = state;
|
|
3466
|
+
if (focusWord && key === '') {
|
|
3467
|
+
return cancelTypeAhead(state);
|
|
3468
|
+
}
|
|
3469
|
+
if (!isAscii(key)) {
|
|
3470
|
+
return state;
|
|
3471
|
+
}
|
|
3472
|
+
const newFocusWord = focusWord + key.toLowerCase();
|
|
3473
|
+
const itemNames = items.map(item => item.name);
|
|
3474
|
+
const matchingIndex = filterByFocusWord(itemNames, focusedIndex, newFocusWord);
|
|
3475
|
+
if (timeout) {
|
|
3476
|
+
clearTimeout(timeout);
|
|
3477
|
+
}
|
|
3478
|
+
|
|
3479
|
+
// @ts-ignore
|
|
3480
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
3481
|
+
timeout = setTimeout(async () => {
|
|
3482
|
+
await invoke('Explorer.cancelTypeAhead');
|
|
3483
|
+
}, focusWordTimeout);
|
|
3484
|
+
if (matchingIndex === -1) {
|
|
3485
|
+
return {
|
|
3486
|
+
...state,
|
|
3487
|
+
focusWord: newFocusWord
|
|
3488
|
+
};
|
|
3489
|
+
}
|
|
3490
|
+
return {
|
|
3491
|
+
...state,
|
|
3492
|
+
focusWord: newFocusWord,
|
|
3493
|
+
focusedIndex: matchingIndex
|
|
3494
|
+
};
|
|
3495
|
+
};
|
|
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
|
+
|
|
3338
3516
|
// TODO add lots of tests for this
|
|
3339
3517
|
const updateRoot = async state1 => {
|
|
3340
3518
|
// @ts-ignore
|
|
@@ -3349,7 +3527,7 @@ const updateRoot = async state1 => {
|
|
|
3349
3527
|
// if (state2.disposed || state2.root !== state1.root) {
|
|
3350
3528
|
// return state2
|
|
3351
3529
|
// }
|
|
3352
|
-
const newDirents = mergeDirents
|
|
3530
|
+
const newDirents = mergeDirents(state1.items, topLevelDirents);
|
|
3353
3531
|
const state3 = {
|
|
3354
3532
|
...state1,
|
|
3355
3533
|
items: newDirents
|
|
@@ -3837,70 +4015,35 @@ const openContainingFolder = async state => {
|
|
|
3837
4015
|
return state;
|
|
3838
4016
|
};
|
|
3839
4017
|
|
|
3840
|
-
|
|
3841
|
-
const
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
await remove(absolutePath);
|
|
3853
|
-
} catch {
|
|
3854
|
-
// TODO vscode shows error as alert (no stacktrace) and retry button
|
|
3855
|
-
// maybe should show alert as well, but where to put stacktrace?
|
|
3856
|
-
// on web should probably show notification (dialog)
|
|
3857
|
-
// ErrorHandling.handleError(error)
|
|
3858
|
-
// await ErrorHandling.showErrorDialog(error)
|
|
3859
|
-
return state;
|
|
3860
|
-
}
|
|
3861
|
-
// TODO avoid state mutation
|
|
3862
|
-
// @ts-ignore
|
|
3863
|
-
const newVersion = ++state.version;
|
|
3864
|
-
// TODO race condition
|
|
3865
|
-
// const newState = await loadContent(state:any)
|
|
3866
|
-
// @ts-ignore
|
|
3867
|
-
if (state.version !== newVersion || state.disposed) {
|
|
3868
|
-
return state;
|
|
3869
|
-
}
|
|
3870
|
-
// TODO is it possible to make this more functional instead of mutating state?
|
|
3871
|
-
// maybe every function returns a new state?
|
|
3872
|
-
const index = state.items.indexOf(dirent);
|
|
3873
|
-
let deleteEnd = index + 1;
|
|
3874
|
-
for (; deleteEnd < state.items.length; deleteEnd++) {
|
|
3875
|
-
if (state.items[deleteEnd].depth <= dirent.depth) {
|
|
3876
|
-
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
|
|
3877
4030
|
}
|
|
3878
4031
|
}
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
let indexToFocus = -1;
|
|
3883
|
-
if (newDirents.length === 0) {
|
|
3884
|
-
indexToFocus = -1;
|
|
3885
|
-
} else if (index < state.focusedIndex) {
|
|
3886
|
-
indexToFocus = state.focusedIndex - 1;
|
|
3887
|
-
} else if (index === state.focusedIndex) {
|
|
3888
|
-
indexToFocus = Math.max(state.focusedIndex - 1, 0);
|
|
3889
|
-
} else {
|
|
3890
|
-
indexToFocus = Math.max(state.focusedIndex - 1, 0);
|
|
3891
|
-
}
|
|
3892
|
-
const visible = newDirents.slice(state.minLineY, state.maxLineY);
|
|
4032
|
+
};
|
|
4033
|
+
|
|
4034
|
+
const removeDirent = async state => {
|
|
3893
4035
|
const {
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
} =
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
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;
|
|
3904
4047
|
};
|
|
3905
4048
|
|
|
3906
4049
|
const getNewDirentsForRename = (items, focusedIndex) => {
|
|
@@ -4030,6 +4173,7 @@ const HandleInputBlur = 'handleInputBlur';
|
|
|
4030
4173
|
const HandleInputClick = 'handleInputClick';
|
|
4031
4174
|
const HandleListBlur = 'handleListBlur';
|
|
4032
4175
|
const HandleListFocus = 'handleListFocus';
|
|
4176
|
+
const HandleListKeyDown = 'handleListKeyDown';
|
|
4033
4177
|
const HandlePointerDown = 'handlePointerDown';
|
|
4034
4178
|
const HandleWheel = 'handleWheel';
|
|
4035
4179
|
|
|
@@ -4214,7 +4358,8 @@ const getExplorerVirtualDom = (visibleItems, focusedIndex, root, isWide, focused
|
|
|
4214
4358
|
onDrop: HandleDrop,
|
|
4215
4359
|
onFocus: HandleListFocus,
|
|
4216
4360
|
onPointerDown: HandlePointerDown,
|
|
4217
|
-
onWheel: HandleWheel
|
|
4361
|
+
onWheel: HandleWheel,
|
|
4362
|
+
onKeyDown: HandleListKeyDown
|
|
4218
4363
|
}, ...visibleItems.flatMap(getExplorerItemVirtualDom)];
|
|
4219
4364
|
return dom;
|
|
4220
4365
|
};
|
|
@@ -4480,6 +4625,10 @@ const renderEventListeners = () => {
|
|
|
4480
4625
|
return [{
|
|
4481
4626
|
name: HandleInputBlur,
|
|
4482
4627
|
params: ['handleInputBlur']
|
|
4628
|
+
}, {
|
|
4629
|
+
name: HandleListKeyDown,
|
|
4630
|
+
params: ['handleKeyDown', 'event.key'],
|
|
4631
|
+
preventDefault: true
|
|
4483
4632
|
}, {
|
|
4484
4633
|
name: HandleListFocus,
|
|
4485
4634
|
params: ['handleFocus', 'event.isTrusted', 'event.target.className']
|
|
@@ -4880,6 +5029,8 @@ const updateEditingValue = async (state, value, inputSource = User) => {
|
|
|
4880
5029
|
|
|
4881
5030
|
const commandMap = {
|
|
4882
5031
|
'Explorer.acceptEdit': wrapCommand(acceptEdit),
|
|
5032
|
+
'Explorer.handleKeyDown': wrapCommand(handleKeyDown),
|
|
5033
|
+
'Explorer.cancelTypeAhead': wrapCommand(cancelTypeAhead),
|
|
4883
5034
|
'Explorer.cancelEdit': wrapCommand(cancelEdit),
|
|
4884
5035
|
'Explorer.collapseAll': wrapCommand(collapseAll),
|
|
4885
5036
|
'Explorer.copyPath': wrapCommand(copyPath),
|