@lvce-editor/explorer-view 2.53.0 → 2.55.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 +149 -79
- package/package.json +1 -1
|
@@ -889,7 +889,7 @@ const Copy$2 = 3;
|
|
|
889
889
|
const Rename$2 = 4;
|
|
890
890
|
|
|
891
891
|
const rpcs = Object.create(null);
|
|
892
|
-
const set$
|
|
892
|
+
const set$g = (id, rpc) => {
|
|
893
893
|
rpcs[id] = rpc;
|
|
894
894
|
};
|
|
895
895
|
const get$1 = id => {
|
|
@@ -913,7 +913,7 @@ const create$2 = rpcId => {
|
|
|
913
913
|
return rpc.invokeAndTransfer(method, ...params);
|
|
914
914
|
},
|
|
915
915
|
set(rpc) {
|
|
916
|
-
set$
|
|
916
|
+
set$g(rpcId, rpc);
|
|
917
917
|
},
|
|
918
918
|
async dispose() {
|
|
919
919
|
const rpc = get$1(rpcId);
|
|
@@ -1005,9 +1005,6 @@ const dirname = (pathSeparator, path) => {
|
|
|
1005
1005
|
const dirname2 = path => {
|
|
1006
1006
|
return dirname('/', path);
|
|
1007
1007
|
};
|
|
1008
|
-
const join = (pathSeparator, ...parts) => {
|
|
1009
|
-
return parts.join(pathSeparator);
|
|
1010
|
-
};
|
|
1011
1008
|
const getBaseName = (pathSeparator, path) => {
|
|
1012
1009
|
return path.slice(path.lastIndexOf(pathSeparator) + 1);
|
|
1013
1010
|
};
|
|
@@ -1844,6 +1841,7 @@ const writeText = async text => {
|
|
|
1844
1841
|
await invoke$1('ClipBoard.writeText', /* text */text);
|
|
1845
1842
|
};
|
|
1846
1843
|
const readNativeFiles = async () => {
|
|
1844
|
+
// @ts-ignore
|
|
1847
1845
|
return invoke$1('ClipBoard.readNativeFiles');
|
|
1848
1846
|
};
|
|
1849
1847
|
const writeNativeFiles = async (type, files) => {
|
|
@@ -3361,12 +3359,12 @@ const uploadFileSystemHandles = async (root, pathSeparator, fileSystemHandles) =
|
|
|
3361
3359
|
return true;
|
|
3362
3360
|
};
|
|
3363
3361
|
|
|
3364
|
-
const mergeDirents$
|
|
3362
|
+
const mergeDirents$1 = (oldDirents, newDirents) => {
|
|
3365
3363
|
return newDirents;
|
|
3366
3364
|
};
|
|
3367
3365
|
const getMergedDirents$2 = async (root, pathSeparator, dirents) => {
|
|
3368
3366
|
const childDirents = await getChildDirents(pathSeparator, root, 0);
|
|
3369
|
-
const mergedDirents = mergeDirents$
|
|
3367
|
+
const mergedDirents = mergeDirents$1(dirents, childDirents);
|
|
3370
3368
|
return mergedDirents;
|
|
3371
3369
|
};
|
|
3372
3370
|
const handleDrop$2 = async (state, fileHandles, files) => {
|
|
@@ -3414,12 +3412,12 @@ const copyFilesElectron = async (root, pathSeparator, fileHandles, files, paths)
|
|
|
3414
3412
|
await applyFileOperations(operations);
|
|
3415
3413
|
};
|
|
3416
3414
|
|
|
3417
|
-
const mergeDirents
|
|
3415
|
+
const mergeDirents = (oldDirents, newDirents) => {
|
|
3418
3416
|
return newDirents;
|
|
3419
3417
|
};
|
|
3420
3418
|
const getMergedDirents$1 = async (root, pathSeparator, dirents) => {
|
|
3421
3419
|
const childDirents = await getChildDirents(pathSeparator, root, 0);
|
|
3422
|
-
const mergedDirents = mergeDirents
|
|
3420
|
+
const mergedDirents = mergeDirents(dirents, childDirents);
|
|
3423
3421
|
return mergedDirents;
|
|
3424
3422
|
};
|
|
3425
3423
|
const handleDrop$1 = async (state, fileHandles, files, paths) => {
|
|
@@ -3682,41 +3680,102 @@ const handleKeyDown = (state, key) => {
|
|
|
3682
3680
|
};
|
|
3683
3681
|
};
|
|
3684
3682
|
|
|
3685
|
-
const
|
|
3686
|
-
|
|
3687
|
-
|
|
3683
|
+
const scrollInto = (index, minLineY, maxLineY) => {
|
|
3684
|
+
const diff = maxLineY - minLineY;
|
|
3685
|
+
const smallerHalf = Math.floor(diff / 2);
|
|
3686
|
+
const largerHalf = diff - smallerHalf;
|
|
3687
|
+
if (index < minLineY) {
|
|
3688
|
+
return {
|
|
3689
|
+
newMinLineY: index - smallerHalf,
|
|
3690
|
+
newMaxLineY: index + largerHalf
|
|
3691
|
+
};
|
|
3692
|
+
}
|
|
3693
|
+
if (index >= maxLineY) {
|
|
3694
|
+
return {
|
|
3695
|
+
newMinLineY: index - smallerHalf,
|
|
3696
|
+
newMaxLineY: index + largerHalf
|
|
3697
|
+
};
|
|
3688
3698
|
}
|
|
3689
|
-
return
|
|
3699
|
+
return {
|
|
3700
|
+
newMinLineY: minLineY,
|
|
3701
|
+
newMaxLineY: maxLineY
|
|
3702
|
+
};
|
|
3690
3703
|
};
|
|
3691
3704
|
|
|
3692
|
-
const
|
|
3693
|
-
const
|
|
3694
|
-
|
|
3695
|
-
|
|
3705
|
+
const adjustScrollAfterPaste = (state, focusedIndex) => {
|
|
3706
|
+
const {
|
|
3707
|
+
minLineY,
|
|
3708
|
+
maxLineY,
|
|
3709
|
+
itemHeight
|
|
3710
|
+
} = state;
|
|
3711
|
+
const {
|
|
3712
|
+
newMinLineY,
|
|
3713
|
+
newMaxLineY
|
|
3714
|
+
} = scrollInto(focusedIndex, minLineY, maxLineY);
|
|
3715
|
+
const newDeltaY = newMinLineY * itemHeight;
|
|
3716
|
+
return {
|
|
3717
|
+
...state,
|
|
3718
|
+
focusedIndex,
|
|
3719
|
+
focused: true,
|
|
3720
|
+
minLineY: newMinLineY,
|
|
3721
|
+
maxLineY: newMaxLineY,
|
|
3722
|
+
deltaY: newDeltaY
|
|
3723
|
+
};
|
|
3724
|
+
};
|
|
3725
|
+
|
|
3726
|
+
const generateUniqueName = (baseName, existingPaths, root) => {
|
|
3727
|
+
// Handle files with extensions
|
|
3728
|
+
const lastDotIndex = baseName.lastIndexOf('.');
|
|
3729
|
+
const hasExtension = lastDotIndex !== -1 && lastDotIndex !== 0 && lastDotIndex !== baseName.length - 1;
|
|
3730
|
+
let nameWithoutExtension;
|
|
3731
|
+
let extension;
|
|
3732
|
+
if (hasExtension) {
|
|
3733
|
+
nameWithoutExtension = baseName.slice(0, lastDotIndex);
|
|
3734
|
+
extension = baseName.slice(lastDotIndex);
|
|
3735
|
+
} else {
|
|
3736
|
+
nameWithoutExtension = baseName;
|
|
3737
|
+
extension = '';
|
|
3738
|
+
}
|
|
3739
|
+
|
|
3740
|
+
// Check if original name exists
|
|
3741
|
+
const originalPath = join2(root, baseName);
|
|
3742
|
+
if (!existingPaths.includes(originalPath)) {
|
|
3743
|
+
return baseName;
|
|
3744
|
+
}
|
|
3745
|
+
|
|
3746
|
+
// Try "original copy"
|
|
3747
|
+
const copyName = `${nameWithoutExtension} copy${extension}`;
|
|
3748
|
+
const copyPath = join2(root, copyName);
|
|
3749
|
+
if (!existingPaths.includes(copyPath)) {
|
|
3750
|
+
return copyName;
|
|
3751
|
+
}
|
|
3752
|
+
|
|
3753
|
+
// Try "original copy 1", "original copy 2", etc.
|
|
3754
|
+
let counter = 1;
|
|
3755
|
+
while (true) {
|
|
3756
|
+
const numberedCopyName = `${nameWithoutExtension} copy ${counter}${extension}`;
|
|
3757
|
+
const numberedCopyPath = join2(root, numberedCopyName);
|
|
3758
|
+
if (!existingPaths.includes(numberedCopyPath)) {
|
|
3759
|
+
return numberedCopyName;
|
|
3760
|
+
}
|
|
3761
|
+
counter++;
|
|
3696
3762
|
}
|
|
3697
|
-
return merged;
|
|
3698
3763
|
};
|
|
3699
3764
|
|
|
3700
|
-
|
|
3701
|
-
const
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3765
|
+
const getFileOperationsCopy = (root, existingUris, files) => {
|
|
3766
|
+
const operations = [];
|
|
3767
|
+
for (const file of files) {
|
|
3768
|
+
const baseName = getBaseName('/', file);
|
|
3769
|
+
const uniqueName = generateUniqueName(baseName, existingUris, root);
|
|
3770
|
+
const newUri = join2(root, uniqueName);
|
|
3771
|
+
operations.push({
|
|
3772
|
+
type: Copy$2,
|
|
3773
|
+
from: file,
|
|
3774
|
+
// TODO ensure file is uri
|
|
3775
|
+
path: newUri
|
|
3776
|
+
});
|
|
3705
3777
|
}
|
|
3706
|
-
|
|
3707
|
-
// @ts-ignore
|
|
3708
|
-
const topLevelDirents = await getTopLevelDirents(state1.root, state1.pathSeparator, []);
|
|
3709
|
-
// const state2 = Viewlet.getState('Explorer')
|
|
3710
|
-
// // TODO what if root changes while reading directories?
|
|
3711
|
-
// if (state2.disposed || state2.root !== state1.root) {
|
|
3712
|
-
// return state2
|
|
3713
|
-
// }
|
|
3714
|
-
const newDirents = mergeDirents(state1.items, topLevelDirents);
|
|
3715
|
-
const state3 = {
|
|
3716
|
-
...state1,
|
|
3717
|
-
items: newDirents
|
|
3718
|
-
};
|
|
3719
|
-
return state3;
|
|
3778
|
+
return operations;
|
|
3720
3779
|
};
|
|
3721
3780
|
|
|
3722
3781
|
const handlePasteCopy = async (state, nativeFiles) => {
|
|
@@ -3725,13 +3784,38 @@ const handlePasteCopy = async (state, nativeFiles) => {
|
|
|
3725
3784
|
// TODO handle pasting files into broken symlink
|
|
3726
3785
|
// TODO handle pasting files into hardlink
|
|
3727
3786
|
// TODO what if folder is big and it takes a long time
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3787
|
+
|
|
3788
|
+
// TODO use file operations and bulk edit
|
|
3789
|
+
const {
|
|
3790
|
+
items,
|
|
3791
|
+
root
|
|
3792
|
+
} = state;
|
|
3793
|
+
const existingUris = items.map(item => item.path);
|
|
3794
|
+
const operations = getFileOperationsCopy(root, existingUris, nativeFiles.files);
|
|
3795
|
+
// TODO handle error?
|
|
3796
|
+
await applyFileOperations(operations);
|
|
3797
|
+
|
|
3798
|
+
// TODO use refreshExplorer with the paths that have been affected by file operations
|
|
3733
3799
|
// TODO only update folder at which level it changed
|
|
3734
|
-
|
|
3800
|
+
const latestState = await refresh(state);
|
|
3801
|
+
|
|
3802
|
+
// Focus on the first newly created file and adjust scroll position
|
|
3803
|
+
const newFilePaths = operations.map(operation => operation.path);
|
|
3804
|
+
if (newFilePaths.length > 0) {
|
|
3805
|
+
const firstNewFilePath = newFilePaths[0];
|
|
3806
|
+
const newFileIndex = getIndex(latestState.items, firstNewFilePath);
|
|
3807
|
+
if (newFileIndex !== -1) {
|
|
3808
|
+
return adjustScrollAfterPaste(latestState, newFileIndex);
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3811
|
+
// If there are no items, ensure focusedIndex is 0
|
|
3812
|
+
if (latestState.items.length === 0) {
|
|
3813
|
+
return {
|
|
3814
|
+
...latestState,
|
|
3815
|
+
focusedIndex: 0
|
|
3816
|
+
};
|
|
3817
|
+
}
|
|
3818
|
+
return latestState;
|
|
3735
3819
|
};
|
|
3736
3820
|
|
|
3737
3821
|
const handlePasteCut = async (state, nativeFiles) => {
|
|
@@ -3739,7 +3823,20 @@ const handlePasteCut = async (state, nativeFiles) => {
|
|
|
3739
3823
|
const target = `${state.root}${state.pathSeparator}${getBaseName(state.pathSeparator, source)}`;
|
|
3740
3824
|
await rename$1(source, target);
|
|
3741
3825
|
}
|
|
3742
|
-
|
|
3826
|
+
|
|
3827
|
+
// Refresh the state after cut operations
|
|
3828
|
+
const latestState = await refresh(state);
|
|
3829
|
+
|
|
3830
|
+
// Focus on the first pasted file and adjust scroll position
|
|
3831
|
+
if (nativeFiles.files.length > 0) {
|
|
3832
|
+
const firstPastedFile = nativeFiles.files[0];
|
|
3833
|
+
const targetPath = `${state.root}${state.pathSeparator}${getBaseName(state.pathSeparator, firstPastedFile)}`;
|
|
3834
|
+
const pastedFileIndex = getIndex(latestState.items, targetPath);
|
|
3835
|
+
if (pastedFileIndex !== -1) {
|
|
3836
|
+
return adjustScrollAfterPaste(latestState, pastedFileIndex);
|
|
3837
|
+
}
|
|
3838
|
+
}
|
|
3839
|
+
return latestState;
|
|
3743
3840
|
};
|
|
3744
3841
|
|
|
3745
3842
|
const handlePasteNone = async (state, nativeFiles) => {
|
|
@@ -3752,18 +3849,6 @@ const Copy = 'copy';
|
|
|
3752
3849
|
const Cut = 'cut';
|
|
3753
3850
|
|
|
3754
3851
|
const getPasteHandler = type => {
|
|
3755
|
-
// TODO detect cut/paste event, not sure if that is possible
|
|
3756
|
-
// TODO check that pasted folder is not a parent folder of opened folder
|
|
3757
|
-
// TODO support pasting multiple paths
|
|
3758
|
-
// TODO what happens when pasting multiple paths, but some of them error?
|
|
3759
|
-
// how many error messages should be shown? Should the operation be undone?
|
|
3760
|
-
// TODO what if it is a large folder and takes a long time to copy? Should show progress
|
|
3761
|
-
// TODO what if there is a permission error? Probably should show a modal to ask for permission
|
|
3762
|
-
// TODO if error is EEXISTS, just rename the copy (e.g. file-copy-1.txt, file-copy-2.txt)
|
|
3763
|
-
// TODO actual target should be selected folder
|
|
3764
|
-
// TODO but what if a file is currently selected? Then maybe the parent folder
|
|
3765
|
-
// TODO but will it work if the folder is a symlink?
|
|
3766
|
-
// TODO handle error gracefully when copy fails
|
|
3767
3852
|
switch (type) {
|
|
3768
3853
|
case None$3:
|
|
3769
3854
|
return handlePasteNone;
|
|
@@ -3778,6 +3863,9 @@ const getPasteHandler = type => {
|
|
|
3778
3863
|
|
|
3779
3864
|
const handlePaste = async state => {
|
|
3780
3865
|
const nativeFiles = await readNativeFiles();
|
|
3866
|
+
if (!nativeFiles) {
|
|
3867
|
+
return state;
|
|
3868
|
+
}
|
|
3781
3869
|
// TODO detect cut/paste event, not sure if that is possible
|
|
3782
3870
|
// TODO check that pasted folder is not a parent folder of opened folder
|
|
3783
3871
|
// TODO support pasting multiple paths
|
|
@@ -4267,7 +4355,11 @@ const removeDirent = async state => {
|
|
|
4267
4355
|
// TODO use file operations, bulk edit and explorer refresh
|
|
4268
4356
|
await removePaths(toRemove);
|
|
4269
4357
|
const newState = await refresh(state);
|
|
4270
|
-
return
|
|
4358
|
+
return {
|
|
4359
|
+
...newState,
|
|
4360
|
+
focused: true,
|
|
4361
|
+
focus: List
|
|
4362
|
+
};
|
|
4271
4363
|
};
|
|
4272
4364
|
|
|
4273
4365
|
const getEditingType = direntType => {
|
|
@@ -5087,28 +5179,6 @@ const mergeVisibleWithHiddenItems = (visibleItems, hiddenItems) => {
|
|
|
5087
5179
|
return unique;
|
|
5088
5180
|
};
|
|
5089
5181
|
|
|
5090
|
-
const scrollInto = (index, minLineY, maxLineY) => {
|
|
5091
|
-
const diff = maxLineY - minLineY;
|
|
5092
|
-
const smallerHalf = Math.floor(diff / 2);
|
|
5093
|
-
const largerHalf = diff - smallerHalf;
|
|
5094
|
-
if (index < minLineY) {
|
|
5095
|
-
return {
|
|
5096
|
-
newMinLineY: index - smallerHalf,
|
|
5097
|
-
newMaxLineY: index + largerHalf
|
|
5098
|
-
};
|
|
5099
|
-
}
|
|
5100
|
-
if (index >= maxLineY) {
|
|
5101
|
-
return {
|
|
5102
|
-
newMinLineY: index - smallerHalf,
|
|
5103
|
-
newMaxLineY: index + largerHalf
|
|
5104
|
-
};
|
|
5105
|
-
}
|
|
5106
|
-
return {
|
|
5107
|
-
newMinLineY: minLineY,
|
|
5108
|
-
newMaxLineY: maxLineY
|
|
5109
|
-
};
|
|
5110
|
-
};
|
|
5111
|
-
|
|
5112
5182
|
// TODO maybe just insert items into explorer and refresh whole explorer
|
|
5113
5183
|
const revealItemHidden = async (state, uri) => {
|
|
5114
5184
|
const {
|