@lvce-editor/explorer-view 2.4.0 → 2.6.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.
@@ -1845,7 +1845,7 @@ const focusPrevious = state => {
1845
1845
  }
1846
1846
  };
1847
1847
 
1848
- const commandIds = ['acceptEdit', 'cancelEdit', 'collapseAll', 'copyPath', 'copyRelativePath', 'expandAll', 'expandRecursively', 'focus', 'focusFirst', 'focusIndex', 'focusLast', 'focusNext', 'focusNone', 'focusPrevious', 'getFocusedDirent', 'handleArrowLeft', 'handleArrowLeft', 'handleArrowRight', 'handleArrowRight', 'handleBlur', 'handleClick', 'handleClickAt', 'handleClickCurrent', 'handleClickCurrentButKeepFocus', 'handleClickOpenFolder', 'handleContextMenu', 'handleCopy', 'handleDragOver', 'handleDrop', 'handleFocus', 'handleIconThemeChange', 'handleLanguagesChanged', 'handleMouseEnter', 'handleMouseLeave', 'handlePaste', 'handlePointerDown', 'handleUpload', 'handleWheel', 'handleWorkspaceChange', 'hotReload', 'newFile', 'newFolder', 'openContainingFolder', 'refresh', 'refresh', 'revealItem', 'removeDirent', 'rename', 'renameDirent', 'revealItem', 'scrollDown', 'scrollUp', 'setDeltaY', 'renderEventListeners', 'updateEditingValue', 'updateIcons'];
1848
+ const commandIds = ['acceptEdit', 'cancelEdit', 'collapseAll', 'copyPath', 'copyRelativePath', 'expandAll', 'expandRecursively', 'focus', 'focusFirst', 'focusIndex', 'focusLast', 'focusNext', 'focusNone', 'focusPrevious', 'getFocusedDirent', 'handleArrowLeft', 'handleArrowLeft', 'handleArrowRight', 'handleArrowRight', 'handleBlur', 'handleClick', 'handleClickAt', 'handleClickCurrent', 'handleClickCurrentButKeepFocus', 'handleClickOpenFolder', 'handleContextMenu', 'handleCopy', 'handleDragLeave', 'handleDragOver', 'handleDrop', 'handleFocus', 'handleIconThemeChange', 'handleLanguagesChanged', 'handleMouseEnter', 'handleMouseLeave', 'handlePaste', 'handlePointerDown', 'handleUpload', 'handleWheel', 'handleWorkspaceChange', 'hotReload', 'newFile', 'newFolder', 'openContainingFolder', 'refresh', 'refresh', 'removeDirent', 'rename', 'renameDirent', 'renderEventListeners', 'revealItem', 'revealItem', 'scrollDown', 'scrollUp', 'setDeltaY', 'updateEditingValue', 'updateIcons'];
1849
1849
 
1850
1850
  const getCommandIds = () => {
1851
1851
  return commandIds;
@@ -2010,7 +2010,7 @@ const rename = () => {
2010
2010
  const deleteItem = () => {
2011
2011
  return i18nString(Delete);
2012
2012
  };
2013
- const refresh = () => {
2013
+ const refresh$1 = () => {
2014
2014
  return i18nString(RefreshExplorer);
2015
2015
  };
2016
2016
  const collapseAll = () => {
@@ -2561,6 +2561,19 @@ const handleCopy = async state => {
2561
2561
  return state;
2562
2562
  };
2563
2563
 
2564
+ const handleDragLeave = state => {
2565
+ const {
2566
+ dropTargets
2567
+ } = state;
2568
+ if (dropTargets.length === 0) {
2569
+ return state;
2570
+ }
2571
+ return {
2572
+ ...state,
2573
+ dropTargets: []
2574
+ };
2575
+ };
2576
+
2564
2577
  const canBeDroppedInto = dirent => {
2565
2578
  if (!dirent) {
2566
2579
  return false;
@@ -2624,6 +2637,52 @@ const handleDragOver = (state, x, y) => {
2624
2637
  };
2625
2638
  };
2626
2639
 
2640
+ const getTopLevelDirents = (root, pathSeparator, excluded) => {
2641
+ if (!root) {
2642
+ return [];
2643
+ }
2644
+ return getChildDirents(pathSeparator, {
2645
+ depth: 0,
2646
+ path: root,
2647
+ type: Directory
2648
+ }, excluded);
2649
+ };
2650
+
2651
+ const mergeDirents$2 = (oldDirents, newDirents) => {
2652
+ const merged = [];
2653
+ for (const newDirent of newDirents) {
2654
+ merged.push(newDirent);
2655
+ }
2656
+ return merged;
2657
+ };
2658
+
2659
+ // TODO add lots of tests for this
2660
+ const refresh = async state1 => {
2661
+ const topLevelDirents = await getTopLevelDirents(state1.root, state1.pathSeparator, []);
2662
+ const newDirents = mergeDirents$2(state1.items, topLevelDirents);
2663
+ const state3 = {
2664
+ ...state1,
2665
+ items: newDirents
2666
+ };
2667
+ return state3;
2668
+ };
2669
+
2670
+ const applyOperation = operation => {
2671
+ if (operation.type === 'createFolder') {
2672
+ return mkdir(operation.path);
2673
+ }
2674
+ if (operation.type === 'copy') {
2675
+ return copy$1(operation.from || '', operation.path);
2676
+ }
2677
+ return writeFile(operation.path, operation.text);
2678
+ };
2679
+ const applyFileOperations = async operations => {
2680
+ // TODO run operations in parallel if possible
2681
+ for (const operation of operations) {
2682
+ await applyOperation(operation);
2683
+ }
2684
+ };
2685
+
2627
2686
  const getChildHandles = async fileHandle => {
2628
2687
  // @ts-ignore
2629
2688
  const values = fileHandle.values();
@@ -2661,11 +2720,35 @@ const createUploadTree = async (root, fileHandles) => {
2661
2720
  return uploadTree;
2662
2721
  };
2663
2722
 
2723
+ const getFileOperations = (root, uploadTree) => {
2724
+ const operations = [];
2725
+ const processTree = (tree, currentPath) => {
2726
+ for (const [path, value] of Object.entries(tree)) {
2727
+ const fullPath = currentPath ? `${currentPath}/${path}` : path;
2728
+ if (typeof value === 'object') {
2729
+ operations.push({
2730
+ type: 'createFolder',
2731
+ path: `${root}/${fullPath}`,
2732
+ text: ''
2733
+ });
2734
+ processTree(value, fullPath);
2735
+ } else if (typeof value === 'string') {
2736
+ operations.push({
2737
+ type: 'createFile',
2738
+ path: `${root}/${fullPath}`,
2739
+ text: value
2740
+ });
2741
+ }
2742
+ }
2743
+ };
2744
+ processTree(uploadTree, '');
2745
+ return operations;
2746
+ };
2747
+
2664
2748
  const uploadFileSystemHandles = async (root, pathSeparator, fileSystemHandles) => {
2665
2749
  const uploadTree = await createUploadTree(root, fileSystemHandles);
2666
- console.log({
2667
- uploadTree
2668
- });
2750
+ const fileOperations = getFileOperations(root, uploadTree);
2751
+ await applyFileOperations(fileOperations);
2669
2752
 
2670
2753
  // TODO
2671
2754
  // 1. in electron, use webutils.getPathForFile to see if a path is available
@@ -2675,7 +2758,7 @@ const uploadFileSystemHandles = async (root, pathSeparator, fileSystemHandles) =
2675
2758
  return true;
2676
2759
  };
2677
2760
 
2678
- const mergeDirents$2 = (oldDirents, newDirents) => {
2761
+ const mergeDirents$1 = (oldDirents, newDirents) => {
2679
2762
  return newDirents;
2680
2763
  };
2681
2764
  const getMergedDirents$2 = async (root, pathSeparator, dirents) => {
@@ -2683,18 +2766,22 @@ const getMergedDirents$2 = async (root, pathSeparator, dirents) => {
2683
2766
  path: root,
2684
2767
  depth: 0
2685
2768
  });
2686
- const mergedDirents = mergeDirents$2(dirents, childDirents);
2769
+ const mergedDirents = mergeDirents$1(dirents, childDirents);
2687
2770
  return mergedDirents;
2688
2771
  };
2689
- const handleDrop$2 = async (state, files) => {
2772
+ const handleDrop$2 = async (state, fileHandles, files) => {
2690
2773
  const {
2691
2774
  root,
2692
2775
  pathSeparator,
2693
2776
  items
2694
2777
  } = state;
2695
- const handled = await uploadFileSystemHandles(root, pathSeparator, files);
2778
+ const handled = await uploadFileSystemHandles(root, pathSeparator, fileHandles);
2696
2779
  if (handled) {
2697
- return state;
2780
+ const updated = await refresh(state);
2781
+ return {
2782
+ ...updated,
2783
+ dropTargets: []
2784
+ };
2698
2785
  }
2699
2786
  const mergedDirents = await getMergedDirents$2(root, pathSeparator, items);
2700
2787
  return {
@@ -2704,38 +2791,60 @@ const handleDrop$2 = async (state, files) => {
2704
2791
  };
2705
2792
  };
2706
2793
 
2794
+ const getFileOperationsElectron = async (root, paths, fileHandles) => {
2795
+ const operations = [];
2796
+ for (let i = 0; i < paths.length; i++) {
2797
+ const fileHandle = fileHandles[i];
2798
+ const name = fileHandle.name;
2799
+ const path = paths[i];
2800
+ operations.push({
2801
+ type: 'copy',
2802
+ path: `${root}/${name}`,
2803
+ text: '',
2804
+ from: path
2805
+ });
2806
+ }
2807
+ return operations;
2808
+ };
2809
+
2707
2810
  const getFilePathElectron = async file => {
2708
- return invoke('GetFilePathElectron.getFilePathElectron', file);
2811
+ return invoke('FileSystemHandle.getFilePathElectron', file);
2709
2812
  };
2710
2813
 
2711
- const mergeDirents$1 = (oldDirents, newDirents) => {
2712
- return newDirents;
2814
+ const getFilepath = async file => {
2815
+ return getFilePathElectron(file);
2816
+ };
2817
+ const getFilePaths = async files => {
2818
+ const promises = files.map(getFilepath);
2819
+ const paths = await Promise.all(promises);
2820
+ return paths;
2713
2821
  };
2714
2822
 
2715
2823
  // TODO copy files in parallel
2716
- const copyFilesElectron = async (root, pathSeparator, files) => {
2717
- for (const file of files) {
2718
- const from = await getFilePathElectron(file);
2719
- // const from = file.path
2720
- const to = join(pathSeparator, root, file.name);
2721
- await copy$1(from, to);
2722
- }
2824
+ const copyFilesElectron = async (root, pathSeparator, fileHandles, files) => {
2825
+ const paths = await getFilePaths(files);
2826
+ const operations = await getFileOperationsElectron(root, paths, fileHandles);
2827
+ await applyFileOperations(operations);
2828
+ };
2829
+
2830
+ const mergeDirents = (oldDirents, newDirents) => {
2831
+ return newDirents;
2723
2832
  };
2724
2833
  const getMergedDirents$1 = async (root, pathSeparator, dirents) => {
2725
2834
  const childDirents = await getChildDirents(pathSeparator, {
2726
2835
  path: root,
2727
2836
  depth: 0
2728
2837
  });
2729
- const mergedDirents = mergeDirents$1(dirents, childDirents);
2838
+ const mergedDirents = mergeDirents(dirents, childDirents);
2730
2839
  return mergedDirents;
2731
2840
  };
2732
- const handleDrop$1 = async (state, files) => {
2841
+ const handleDrop$1 = async (state, fileHandles, files) => {
2733
2842
  const {
2734
2843
  root,
2735
2844
  pathSeparator,
2736
2845
  items
2737
2846
  } = state;
2738
- await copyFilesElectron(root, pathSeparator, files);
2847
+ await copyFilesElectron(root, pathSeparator, fileHandles, files);
2739
2848
  const mergedDirents = await getMergedDirents$1(root, pathSeparator, items);
2740
2849
  return {
2741
2850
  ...state,
@@ -2744,16 +2853,18 @@ const handleDrop$1 = async (state, files) => {
2744
2853
  };
2745
2854
  };
2746
2855
 
2856
+ const Electron = 2;
2857
+
2747
2858
  const getModule = isElectron => {
2748
2859
  if (isElectron) {
2749
2860
  return handleDrop$1;
2750
2861
  }
2751
2862
  return handleDrop$2;
2752
2863
  };
2753
- const handleDropRoot = async (state, files) => {
2754
- // @ts-ignore
2755
- const fn = getModule(state.isElectron);
2756
- return fn(state, files);
2864
+ const handleDropRoot = async (state, fileHandles, files) => {
2865
+ const isElectron = state.platform === Electron;
2866
+ const fn = getModule(isElectron);
2867
+ return fn(state, fileHandles, files);
2757
2868
  };
2758
2869
 
2759
2870
  const getEndIndex = (items, index, dirent) => {
@@ -2773,13 +2884,13 @@ const getMergedDirents = (items, index, dirent, childDirents) => {
2773
2884
  }, ...childDirents, ...items.slice(endIndex)];
2774
2885
  return mergedDirents;
2775
2886
  };
2776
- const handleDropIntoFolder = async (state, dirent, index, files) => {
2887
+ const handleDropIntoFolder = async (state, dirent, index, fileHandles, files) => {
2777
2888
  const {
2778
2889
  pathSeparator,
2779
2890
  items
2780
2891
  } = state;
2781
2892
  // @ts-ignore
2782
- for (const file of files) {
2893
+ for (const file of fileHandles) {
2783
2894
  // TODO path basename
2784
2895
  const baseName = file.name;
2785
2896
  const to = dirent.path + pathSeparator + baseName;
@@ -2795,18 +2906,18 @@ const handleDropIntoFolder = async (state, dirent, index, files) => {
2795
2906
  dropTargets: []
2796
2907
  };
2797
2908
  };
2798
- const handleDropIntoFile = (state, dirent, index, files) => {
2909
+ const handleDropIntoFile = (state, dirent, index, fileHandles, files) => {
2799
2910
  const {
2800
2911
  items
2801
2912
  } = state;
2802
2913
  const parentIndex = getParentStartIndex(items, index);
2803
2914
  if (parentIndex === -1) {
2804
- return handleDropRoot(state, files);
2915
+ return handleDropRoot(state, fileHandles, files);
2805
2916
  }
2806
2917
  // @ts-ignore
2807
2918
  return handleDropIndex(parentIndex);
2808
2919
  };
2809
- const handleDropIndex = async (state, files, index) => {
2920
+ const handleDropIndex = async (state, fileHandles, files, index) => {
2810
2921
  const {
2811
2922
  items
2812
2923
  } = state;
@@ -2817,9 +2928,9 @@ const handleDropIndex = async (state, files, index) => {
2817
2928
  switch (dirent.type) {
2818
2929
  case Directory:
2819
2930
  case DirectoryExpanded:
2820
- return handleDropIntoFolder(state, dirent, index, files);
2931
+ return handleDropIntoFolder(state, dirent, index, fileHandles);
2821
2932
  case File:
2822
- return handleDropIntoFile(state, dirent, index, files);
2933
+ return handleDropIntoFile(state, dirent, index, fileHandles, files);
2823
2934
  default:
2824
2935
  return state;
2825
2936
  }
@@ -2839,12 +2950,14 @@ const getFileHandles = async fileIds => {
2839
2950
  return files;
2840
2951
  };
2841
2952
 
2842
- const handleDrop = async (state, x, y, fileIds) => {
2953
+ const handleDrop = async (state, x, y, fileIds, fileList) => {
2843
2954
  try {
2844
- const files = await getFileHandles(fileIds);
2955
+ // @ts-ignore
2956
+ const files = [...fileList];
2957
+ const fileHandles = await getFileHandles(fileIds);
2845
2958
  const index = getIndexFromPosition(state, x, y);
2846
2959
  const fn = getDropHandler(index);
2847
- const result = await fn(state, files, index);
2960
+ const result = await fn(state, fileHandles, files, index);
2848
2961
  return result;
2849
2962
  } catch (error) {
2850
2963
  throw new VError(error, 'Failed to drop files');
@@ -2891,25 +3004,6 @@ const handleIconThemeChange = state => {
2891
3004
  return updateIcons(state);
2892
3005
  };
2893
3006
 
2894
- const getTopLevelDirents = (root, pathSeparator, excluded) => {
2895
- if (!root) {
2896
- return [];
2897
- }
2898
- return getChildDirents(pathSeparator, {
2899
- depth: 0,
2900
- path: root,
2901
- type: Directory
2902
- }, excluded);
2903
- };
2904
-
2905
- const mergeDirents = (oldDirents, newDirents) => {
2906
- const merged = [];
2907
- for (const newDirent of newDirents) {
2908
- merged.push(newDirent);
2909
- }
2910
- return merged;
2911
- };
2912
-
2913
3007
  // TODO add lots of tests for this
2914
3008
  const updateRoot = async state1 => {
2915
3009
  // @ts-ignore
@@ -2918,13 +3012,13 @@ const updateRoot = async state1 => {
2918
3012
  }
2919
3013
  // const file = nativeFiles.files[0]
2920
3014
  // @ts-ignore
2921
- const topLevelDirents = await getTopLevelDirents(state1.root, state1.pathSeparator);
3015
+ const topLevelDirents = await getTopLevelDirents(state1.root, state1.pathSeparator, []);
2922
3016
  // const state2 = Viewlet.getState('Explorer')
2923
3017
  // // TODO what if root changes while reading directories?
2924
3018
  // if (state2.disposed || state2.root !== state1.root) {
2925
3019
  // return state2
2926
3020
  // }
2927
- const newDirents = mergeDirents(state1.items, topLevelDirents);
3021
+ const newDirents = mergeDirents$2(state1.items, topLevelDirents);
2928
3022
  const state3 = {
2929
3023
  ...state1,
2930
3024
  items: newDirents
@@ -3453,6 +3547,7 @@ const HandlePointerDown = 'handlePointerDown';
3453
3547
  const HandleWheel = 'handleWheel';
3454
3548
  const HandleDragOver = 'handleDragOver';
3455
3549
  const HandleDrop = 'handleDrop';
3550
+ const HandleDragLeave = 'handleDragLeave';
3456
3551
 
3457
3552
  const mergeClassNames = (...classNames) => {
3458
3553
  return classNames.filter(Boolean).join(' ');
@@ -3604,6 +3699,7 @@ const getExplorerVirtualDom = (visibleItems, focusedIndex, root, isWide, focused
3604
3699
  onBlur: HandleListBlur,
3605
3700
  onClick: HandleClick,
3606
3701
  onContextMenu: HandleContextMenu,
3702
+ onDragLeave: HandleDragLeave,
3607
3703
  onDragOver: HandleDragOver,
3608
3704
  onDrop: HandleDrop,
3609
3705
  onFocus: HandleListFocus,
@@ -3775,7 +3871,7 @@ const getActions = root => {
3775
3871
  command: 'newFolder'
3776
3872
  }, {
3777
3873
  type: Button,
3778
- id: refresh(),
3874
+ id: refresh$1(),
3779
3875
  icon: Refresh,
3780
3876
  command: 'refresh'
3781
3877
  }, {
@@ -3876,8 +3972,11 @@ const renderEventListeners = () => {
3876
3972
  preventDefault: true
3877
3973
  }, {
3878
3974
  name: HandleDrop,
3879
- params: ['handleDrop', 'event.clientX', 'event.clientY', 'event.dataTransfer.files2'],
3975
+ params: ['handleDrop', 'event.clientX', 'event.clientY', 'event.dataTransfer.files2', 'event.dataTransfer.files'],
3880
3976
  preventDefault: true
3977
+ }, {
3978
+ name: HandleDragLeave,
3979
+ params: ['handleDragLeave']
3881
3980
  }];
3882
3981
  };
3883
3982
 
@@ -4219,6 +4318,7 @@ const commandMap = {
4219
4318
  'Explorer.handleClickOpenFolder': wrapCommand(handleClickOpenFolder),
4220
4319
  'Explorer.handleContextMenu': wrapCommand(handleContextMenu),
4221
4320
  'Explorer.handleCopy': wrapCommand(handleCopy),
4321
+ 'Explorer.handleDragLeave': wrapCommand(handleDragLeave),
4222
4322
  'Explorer.handleDragOver': wrapCommand(handleDragOver),
4223
4323
  'Explorer.handleDrop': wrapCommand(handleDrop),
4224
4324
  'Explorer.handleFocus': wrapCommand(handleFocus),
@@ -4232,6 +4332,7 @@ const commandMap = {
4232
4332
  'Explorer.newFile': wrapCommand(newFile),
4233
4333
  'Explorer.newFolder': wrapCommand(newFolder),
4234
4334
  'Explorer.openContainingFolder': wrapCommand(openContainingFolder),
4335
+ 'Explorer.refresh': wrapCommand(refresh),
4235
4336
  'Explorer.removeDirent': wrapCommand(removeDirent),
4236
4337
  'Explorer.renameDirent': wrapCommand(renameDirent),
4237
4338
  'Explorer.restoreState': restoreState,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/explorer-view",
3
- "version": "2.4.0",
3
+ "version": "2.6.0",
4
4
  "description": "Explorer Worker",
5
5
  "repository": {
6
6
  "type": "git",