@lvce-editor/explorer-view 1.5.0 → 1.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.
@@ -949,7 +949,7 @@ const computeExplorerRenamedDirent = (dirents, index, newName) => {
949
949
  const None$3 = 0;
950
950
  const CreateFile = 1;
951
951
  const CreateFolder = 2;
952
- const Rename = 3;
952
+ const Rename$1 = 3;
953
953
 
954
954
  const state = {
955
955
  rpc: undefined
@@ -981,6 +981,9 @@ const stat = async dirent => {
981
981
  const createFile = async uri => {
982
982
  return invoke('FileSystem.createFile', uri);
983
983
  };
984
+ const writeFile = async (uri, content) => {
985
+ return invoke('FileSystem.writeFile', uri, content);
986
+ };
984
987
  const mkdir = async uri => {
985
988
  return invoke('FileSystem.mkdir', uri);
986
989
  };
@@ -1132,13 +1135,57 @@ const acceptEdit = state => {
1132
1135
  return acceptCreate(state, File, createFile);
1133
1136
  case CreateFolder:
1134
1137
  return acceptCreate(state, Directory, mkdir);
1135
- case Rename:
1138
+ case Rename$1:
1136
1139
  return acceptRename(state);
1137
1140
  default:
1138
1141
  return state;
1139
1142
  }
1140
1143
  };
1141
1144
 
1145
+ const cancelEdit = state => {
1146
+ const {
1147
+ editingIndex
1148
+ } = state;
1149
+ return {
1150
+ ...state,
1151
+ focusedIndex: editingIndex,
1152
+ focused: true,
1153
+ editingIndex: -1,
1154
+ editingValue: '',
1155
+ editingType: None$3
1156
+ };
1157
+ };
1158
+
1159
+ const isTopLevel$1 = dirent => {
1160
+ return dirent.depth === 1;
1161
+ };
1162
+
1163
+ const IsTopLevel = {
1164
+ __proto__: null,
1165
+ isTopLevel: isTopLevel$1
1166
+ };
1167
+
1168
+ const toCollapsedDirent = dirent => {
1169
+ if (dirent.type === DirectoryExpanded) {
1170
+ return {
1171
+ ...dirent,
1172
+ type: Directory
1173
+ };
1174
+ }
1175
+ return dirent;
1176
+ };
1177
+
1178
+ const collapseAll$1 = state => {
1179
+ const {
1180
+ items
1181
+ } = state;
1182
+ const newDirents = items.filter(IsTopLevel).map(toCollapsedDirent);
1183
+ return {
1184
+ ...state,
1185
+ items: newDirents
1186
+ };
1187
+ };
1188
+
1142
1189
  const getFocusedDirent$1 = state => {
1143
1190
  const {
1144
1191
  focusedIndex,
@@ -1160,6 +1207,9 @@ const writeText = async text => {
1160
1207
  const readNativeFiles = async () => {
1161
1208
  return invoke('ClipBoard.readNativeFiles');
1162
1209
  };
1210
+ const writeNativeFiles = async (type, files) => {
1211
+ return invoke('ClipBoard.writeNativeFiles', type, files);
1212
+ };
1163
1213
 
1164
1214
  const copyRelativePath$1 = async state => {
1165
1215
  const dirent = getFocusedDirent$1(state);
@@ -1407,6 +1457,7 @@ const makeExpanded = dirent => {
1407
1457
  }
1408
1458
  return dirent;
1409
1459
  };
1460
+
1410
1461
  const expandRecursively = async state => {
1411
1462
  const {
1412
1463
  items,
@@ -1563,29 +1614,12 @@ const focusPrevious = state => {
1563
1614
  }
1564
1615
  };
1565
1616
 
1566
- const None$2 = 'none';
1567
- const Tree = 'tree';
1568
- const TreeItem$1 = 'treeitem';
1569
-
1570
- const Button$1 = 'Button';
1571
- const ButtonPrimary = 'ButtonPrimary';
1572
- const Explorer$1 = 'Explorer';
1573
- const FileIcon = 'FileIcon';
1574
- const InputBox = 'InputBox';
1575
- const Label = 'Label';
1576
- const TreeItem = 'TreeItem';
1577
- const TreeItemActive = 'TreeItemActive';
1578
- const Viewlet = 'Viewlet';
1579
- const Welcome = 'Welcome';
1580
- const WelcomeMessage = 'WelcomeMessage';
1617
+ const Button$2 = 1;
1581
1618
 
1582
- const HandleBlur = 'handleBlur';
1583
- const HandleClick = 'handleClick';
1584
- const handleClickOpenFolder$1 = 'handleClickOpenFolder';
1585
- const HandleContextMenu = 'handleContextMenu';
1586
- const HandleFocus = 'handleFocus';
1587
- const HandlePointerDown = 'handlePointerDown';
1588
- const HandleWheel = 'handleWheel';
1619
+ const CollapseAll = 'CollapseAll';
1620
+ const NewFile$1 = 'NewFile';
1621
+ const NewFolder$1 = 'NewFolder';
1622
+ const Refresh = 'Refresh';
1589
1623
 
1590
1624
  const emptyObject = {};
1591
1625
  const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
@@ -1599,72 +1633,126 @@ const i18nString = (key, placeholders = emptyObject) => {
1599
1633
  return key.replaceAll(RE_PLACEHOLDER, replacer);
1600
1634
  };
1601
1635
 
1602
- /**
1603
- * @enum {string}
1604
- */
1605
- const UiStrings = {
1606
- NewFile: 'New File...',
1607
- NewFolder: 'New Folder...',
1608
- OpenContainingFolder: 'Open Containing Folder',
1609
- OpenInIntegratedTerminal: 'Open in integrated Terminal',
1610
- Cut: 'Cut',
1611
- Copy: 'Copy',
1612
- Paste: 'Paste',
1613
- CopyPath: 'Copy Path',
1614
- CopyRelativePath: 'Copy Relative Path',
1615
- Rename: 'Rename',
1616
- Delete: 'Delete',
1617
- RefreshExplorer: 'Refresh Explorer',
1618
- CollapseAllFoldersInExplorer: 'Collapse All Folders in Explorer',
1619
- Explorer: 'Explorer',
1620
- FilesExplorer: 'Files Explorer',
1621
- YouHaveNotYetOpenedAFolder: 'You have not yet opened a folder',
1622
- OpenFolder: 'Open folder',
1623
- NoFolderOpen: 'No Folder Open'
1624
- };
1625
- const newFile = () => {
1626
- return i18nString(UiStrings.NewFile);
1627
- };
1628
- const newFolder = () => {
1629
- return i18nString(UiStrings.NewFolder);
1636
+ const NewFile = 'New File...';
1637
+ const NewFolder = 'New Folder...';
1638
+ const OpenContainingFolder = 'Open Containing Folder';
1639
+ const OpenInIntegratedTerminal = 'Open in integrated Terminal';
1640
+ const Cut$1 = 'Cut';
1641
+ const Copy$1 = 'Copy';
1642
+ const Paste = 'Paste';
1643
+ const CopyPath = 'Copy Path';
1644
+ const CopyRelativePath = 'Copy Relative Path';
1645
+ const Rename = 'Rename';
1646
+ const Delete$1 = 'Delete';
1647
+ const RefreshExplorer = 'Refresh Explorer';
1648
+ const CollapseAllFoldersInExplorer = 'Collapse All Folders in Explorer';
1649
+ const FilesExplorer = 'Files Explorer';
1650
+ const YouHaveNotYetOpenedAFolder = 'You have not yet opened a folder';
1651
+ const OpenFolder = 'Open folder';
1652
+
1653
+ const newFile$1 = () => {
1654
+ return i18nString(NewFile);
1655
+ };
1656
+ const newFolder$1 = () => {
1657
+ return i18nString(NewFolder);
1630
1658
  };
1631
1659
  const openContainingFolder$1 = () => {
1632
- return i18nString(UiStrings.OpenContainingFolder);
1660
+ return i18nString(OpenContainingFolder);
1633
1661
  };
1634
1662
  const openInIntegratedTerminal = () => {
1635
- return i18nString(UiStrings.OpenInIntegratedTerminal);
1663
+ return i18nString(OpenInIntegratedTerminal);
1636
1664
  };
1637
1665
  const cut = () => {
1638
- return i18nString(UiStrings.Cut);
1666
+ return i18nString(Cut$1);
1639
1667
  };
1640
1668
  const copy = () => {
1641
- return i18nString(UiStrings.Copy);
1669
+ return i18nString(Copy$1);
1642
1670
  };
1643
1671
  const paste = () => {
1644
- return i18nString(UiStrings.Paste);
1672
+ return i18nString(Paste);
1645
1673
  };
1646
1674
  const copyPath = () => {
1647
- return i18nString(UiStrings.CopyPath);
1675
+ return i18nString(CopyPath);
1648
1676
  };
1649
1677
  const copyRelativePath = () => {
1650
- return i18nString(UiStrings.CopyRelativePath);
1678
+ return i18nString(CopyRelativePath);
1651
1679
  };
1652
1680
  const rename = () => {
1653
- return i18nString(UiStrings.Rename);
1681
+ return i18nString(Rename);
1654
1682
  };
1655
1683
  const deleteItem = () => {
1656
- return i18nString(UiStrings.Delete);
1684
+ return i18nString(Delete$1);
1685
+ };
1686
+ const refresh = () => {
1687
+ return i18nString(RefreshExplorer);
1688
+ };
1689
+ const collapseAll = () => {
1690
+ return i18nString(CollapseAllFoldersInExplorer);
1657
1691
  };
1658
1692
  const filesExplorer = () => {
1659
- return i18nString(UiStrings.FilesExplorer);
1693
+ return i18nString(FilesExplorer);
1660
1694
  };
1661
1695
  const youHaveNotYetOpenedAFolder = () => {
1662
- return i18nString(UiStrings.YouHaveNotYetOpenedAFolder);
1696
+ return i18nString(YouHaveNotYetOpenedAFolder);
1663
1697
  };
1664
1698
  const openFolder$1 = () => {
1665
- return i18nString(UiStrings.OpenFolder);
1699
+ return i18nString(OpenFolder);
1700
+ };
1701
+
1702
+ const getActions = root => {
1703
+ if (!root) {
1704
+ return [];
1705
+ }
1706
+ return [{
1707
+ type: Button$2,
1708
+ id: newFile$1(),
1709
+ icon: NewFile$1,
1710
+ command: 'newFile'
1711
+ }, {
1712
+ type: Button$2,
1713
+ id: newFolder$1(),
1714
+ icon: NewFolder$1,
1715
+ command: 'newFolder'
1716
+ }, {
1717
+ type: Button$2,
1718
+ id: refresh(),
1719
+ icon: Refresh,
1720
+ command: 'refresh'
1721
+ }, {
1722
+ type: Button$2,
1723
+ id: collapseAll(),
1724
+ icon: CollapseAll,
1725
+ command: 'collapseAll'
1726
+ }];
1666
1727
  };
1667
1728
 
1729
+ const None$2 = 'none';
1730
+ const ToolBar = 'toolbar';
1731
+ const Tree = 'tree';
1732
+ const TreeItem$1 = 'treeitem';
1733
+
1734
+ const Actions = 'Actions';
1735
+ const Button$1 = 'Button';
1736
+ const ButtonPrimary = 'ButtonPrimary';
1737
+ const Explorer$1 = 'Explorer';
1738
+ const FileIcon = 'FileIcon';
1739
+ const IconButton = 'IconButton';
1740
+ const InputBox = 'InputBox';
1741
+ const Label = 'Label';
1742
+ const TreeItem = 'TreeItem';
1743
+ const TreeItemActive = 'TreeItemActive';
1744
+ const Viewlet = 'Viewlet';
1745
+ const Welcome = 'Welcome';
1746
+ const WelcomeMessage = 'WelcomeMessage';
1747
+
1748
+ const HandleBlur = 'handleBlur';
1749
+ const HandleClick = 'handleClick';
1750
+ const handleClickOpenFolder$1 = 'handleClickOpenFolder';
1751
+ const HandleContextMenu = 'handleContextMenu';
1752
+ const HandleFocus = 'handleFocus';
1753
+ const HandlePointerDown = 'handlePointerDown';
1754
+ const HandleWheel = 'handleWheel';
1755
+
1668
1756
  const Button = 1;
1669
1757
  const Div = 4;
1670
1758
  const Input = 6;
@@ -1972,13 +2060,13 @@ const menuEntrySeparator = {
1972
2060
 
1973
2061
  const menuEntryNewFile = {
1974
2062
  id: 'newFile',
1975
- label: newFile(),
2063
+ label: newFile$1(),
1976
2064
  flags: None$1,
1977
2065
  command: 'Explorer.newFile'
1978
2066
  };
1979
2067
  const menuEntryNewFolder = {
1980
2068
  id: 'newFolder',
1981
- label: newFolder(),
2069
+ label: newFolder$1(),
1982
2070
  flags: None$1,
1983
2071
  command: 'Explorer.newFolder'
1984
2072
  };
@@ -2279,6 +2367,40 @@ const getIndexFromPosition = (state, eventX, eventY) => {
2279
2367
  return index;
2280
2368
  };
2281
2369
 
2370
+ const handleClickDirectory = async (state, dirent, index, keepFocus) => {
2371
+ dirent.type = DirectoryExpanding;
2372
+ // TODO handle error
2373
+ const dirents = await getChildDirents(state.pathSeparator, dirent);
2374
+ const state2 = state;
2375
+ if (!state2) {
2376
+ return state;
2377
+ }
2378
+ // TODO use Viewlet.getState here and check if it exists
2379
+ const newIndex = state2.items.indexOf(dirent);
2380
+ // TODO if viewlet is disposed or root has changed, return
2381
+ if (newIndex === -1) {
2382
+ return state;
2383
+ }
2384
+ const newDirents = [...state2.items];
2385
+ newDirents.splice(newIndex + 1, 0, ...dirents);
2386
+ dirent.type = DirectoryExpanded;
2387
+ dirent.icon = getIcon();
2388
+ const {
2389
+ height,
2390
+ itemHeight,
2391
+ minLineY
2392
+ } = state2;
2393
+ // TODO when focused index has changed while expanding, don't update it
2394
+ const maxLineY = getExplorerMaxLineY(minLineY, height, itemHeight, newDirents.length);
2395
+ return {
2396
+ ...state,
2397
+ items: newDirents,
2398
+ focusedIndex: newIndex,
2399
+ focused: keepFocus,
2400
+ maxLineY
2401
+ };
2402
+ };
2403
+
2282
2404
  const getParentStartIndex = (dirents, index) => {
2283
2405
  const dirent = dirents[index];
2284
2406
  let startIndex = index - 1;
@@ -2291,10 +2413,6 @@ const getParentStartIndex = (dirents, index) => {
2291
2413
  const Keyboard = -1;
2292
2414
  const LeftClick = 0;
2293
2415
 
2294
- const openFolder = async () => {
2295
- // TODO
2296
- };
2297
-
2298
2416
  // TODO viewlet should only have create and refresh functions
2299
2417
  // every thing else can be in a separate module <viewlet>.lazy.js
2300
2418
  // and <viewlet>.ipc.js
@@ -2322,7 +2440,7 @@ const handleIconThemeChange = state => {
2322
2440
  };
2323
2441
 
2324
2442
  // TODO rename dirents to items, then can use virtual list component directly
2325
- const setDeltaY = (state, deltaY) => {
2443
+ const setDeltaY$1 = (state, deltaY) => {
2326
2444
  const {
2327
2445
  itemHeight,
2328
2446
  height,
@@ -2346,93 +2464,11 @@ const setDeltaY = (state, deltaY) => {
2346
2464
  };
2347
2465
  };
2348
2466
  const handleWheel = (state, deltaMode, deltaY) => {
2349
- return setDeltaY(state, state.deltaY + deltaY);
2350
- };
2351
-
2352
- // TODO support multiselection and removing multiple dirents
2353
- const removeDirent = async state => {
2354
- if (state.focusedIndex < 0) {
2355
- return state;
2356
- }
2357
- const dirent = getFocusedDirent$1(state);
2358
- const absolutePath = dirent.path;
2359
- try {
2360
- // TODO handle error
2361
- await remove(absolutePath);
2362
- } catch (error) {
2363
- // TODO vscode shows error as alert (no stacktrace) and retry button
2364
- // maybe should show alert as well, but where to put stacktrace?
2365
- // on web should probably show notification (dialog)
2366
- // ErrorHandling.handleError(error)
2367
- // await ErrorHandling.showErrorDialog(error)
2368
- return;
2369
- }
2370
- // TODO avoid state mutation
2371
- const newVersion = ++state.version;
2372
- // TODO race condition
2373
- // const newState = await loadContent(state:any)
2374
- if (state.version !== newVersion || state.disposed) {
2375
- return state;
2376
- }
2377
- // TODO is it possible to make this more functional instead of mutating state?
2378
- // maybe every function returns a new state?
2379
- const index = state.items.indexOf(dirent);
2380
- let deleteEnd = index + 1;
2381
- for (; deleteEnd < state.items.length; deleteEnd++) {
2382
- if (state.items[deleteEnd].depth <= dirent.depth) {
2383
- break;
2384
- }
2385
- }
2386
- const deleteCount = deleteEnd - index;
2387
- const newDirents = [...state.items];
2388
- newDirents.splice(index, deleteCount);
2389
- let indexToFocus = -1;
2390
- if (newDirents.length === 0) {
2391
- indexToFocus = -1;
2392
- } else if (index < state.focusedIndex) {
2393
- indexToFocus = state.focusedIndex - 1;
2394
- } else if (index === state.focusedIndex) {
2395
- indexToFocus = Math.max(state.focusedIndex - 1, 0);
2396
- } else {
2397
- indexToFocus = Math.max(state.focusedIndex - 1, 0);
2398
- }
2399
- return {
2400
- ...state,
2401
- items: newDirents,
2402
- focusedIndex: indexToFocus
2403
- };
2404
- };
2405
- const renameDirent = state => {
2406
- const {
2407
- focusedIndex,
2408
- items
2409
- } = state;
2410
- const item = items[focusedIndex];
2411
- // Focus.setFocus(FocusKey.ExplorerEditBox)
2412
- return {
2413
- ...state,
2414
- editingIndex: focusedIndex,
2415
- editingType: Rename,
2416
- editingValue: item.name
2417
- };
2467
+ return setDeltaY$1(state, state.deltaY + deltaY);
2418
2468
  };
2419
2469
 
2420
2470
  // TODO use posInSet and setSize properties to compute more effectively
2421
2471
 
2422
- const cancelEdit = state => {
2423
- const {
2424
- editingIndex
2425
- } = state;
2426
- return {
2427
- ...state,
2428
- focusedIndex: editingIndex,
2429
- focused: true,
2430
- editingIndex: -1,
2431
- editingValue: '',
2432
- editingType: None$3
2433
- };
2434
- };
2435
-
2436
2472
  // TODO much shared logic with newFolder
2437
2473
 
2438
2474
  const handleClickFile = async (state, dirent, index, keepFocus = false) => {
@@ -2443,39 +2479,6 @@ const handleClickFile = async (state, dirent, index, keepFocus = false) => {
2443
2479
  focused: keepFocus
2444
2480
  };
2445
2481
  };
2446
- const handleClickDirectory = async (state, dirent, index, keepFocus) => {
2447
- dirent.type = DirectoryExpanding;
2448
- // TODO handle error
2449
- const dirents = await getChildDirents(state.pathSeparator, dirent);
2450
- const state2 = {};
2451
- if (!state2) {
2452
- return state;
2453
- }
2454
- // TODO use Viewlet.getState here and check if it exists
2455
- const newIndex = state2.items.indexOf(dirent);
2456
- // TODO if viewlet is disposed or root has changed, return
2457
- if (newIndex === -1) {
2458
- return state;
2459
- }
2460
- const newDirents = [...state2.items];
2461
- newDirents.splice(newIndex + 1, 0, ...dirents);
2462
- dirent.type = DirectoryExpanded;
2463
- dirent.icon = getIcon();
2464
- const {
2465
- height,
2466
- itemHeight,
2467
- minLineY
2468
- } = state2;
2469
- // TODO when focused index has changed while expanding, don't update it
2470
- const maxLineY = getExplorerMaxLineY(minLineY, height, itemHeight, newDirents.length);
2471
- return {
2472
- ...state,
2473
- items: newDirents,
2474
- focusedIndex: newIndex,
2475
- focused: keepFocus,
2476
- maxLineY
2477
- };
2478
- };
2479
2482
  const handleClickDirectoryExpanded = (state, dirent, index, keepFocus) => {
2480
2483
  const {
2481
2484
  minLineY,
@@ -2625,6 +2628,10 @@ const handleArrowLeft = state => {
2625
2628
 
2626
2629
  // TODO maybe just insert items into explorer and refresh whole explorer
2627
2630
 
2631
+ const openFolder = async () => {
2632
+ // TODO
2633
+ };
2634
+
2628
2635
  const handleClickOpenFolder = async state => {
2629
2636
  await openFolder();
2630
2637
  return state;
@@ -2671,6 +2678,21 @@ const handleContextMenu = (state, button, x, y) => {
2671
2678
  }
2672
2679
  };
2673
2680
 
2681
+ const handleCopy = async state => {
2682
+ // TODO handle multiple files
2683
+ // TODO if not file is selected, what happens?
2684
+ const dirent = getFocusedDirent$1(state);
2685
+ if (!dirent) {
2686
+ console.info('[ViewletExplorer/handleCopy] no dirent selected');
2687
+ return;
2688
+ }
2689
+ const absolutePath = dirent.path;
2690
+ // TODO handle copy error gracefully
2691
+ const files = [absolutePath];
2692
+ await writeNativeFiles('copy', files);
2693
+ return state;
2694
+ };
2695
+
2674
2696
  const getFilePathElectron = async file => {
2675
2697
  return invoke('GetFilePathElectron.getFilePathElectron', file);
2676
2698
  };
@@ -3001,6 +3023,25 @@ const handlePointerDown = (state, button, x, y) => {
3001
3023
  return state;
3002
3024
  };
3003
3025
 
3026
+ const handleUpload = async (state, dirents) => {
3027
+ const {
3028
+ root,
3029
+ pathSeparator
3030
+ } = state;
3031
+ for (const dirent of dirents) {
3032
+ // TODO switch
3033
+ // TODO symlink might not be possible to be copied
3034
+ // TODO create folder if type is 2
3035
+ if (dirent.type === /* File */1) {
3036
+ // TODO reading text might be inefficient for binary files
3037
+ // but not sure how else to send them via jsonrpc
3038
+ const content = await dirent.file.text();
3039
+ const absolutePath = [root, dirent.file.name].join(pathSeparator);
3040
+ await writeFile(absolutePath, content);
3041
+ }
3042
+ }
3043
+ };
3044
+
3004
3045
  const EmptyString = '';
3005
3046
 
3006
3047
  const Fulfilled = 'fulfilled';
@@ -3155,6 +3196,45 @@ const loadContent = async (state, savedState) => {
3155
3196
  };
3156
3197
  };
3157
3198
 
3199
+ const ExplorerEditBox = FocusExplorerEditBox;
3200
+
3201
+ const setFocus = key => {
3202
+ return invoke('Focus.setFocus', key);
3203
+ };
3204
+
3205
+ const newDirent = async (state, editingType) => {
3206
+ // TODO make focus functional instead of side effect
3207
+ await setFocus(ExplorerEditBox);
3208
+ // TODO do it like vscode, select position between folders and files
3209
+ const {
3210
+ focusedIndex,
3211
+ items
3212
+ } = state;
3213
+ if (focusedIndex >= 0) {
3214
+ const dirent = items[focusedIndex];
3215
+ if (dirent.type === Directory) {
3216
+ // TODO handle error
3217
+ // @ts-ignore
3218
+ await undefined(state, dirent, focusedIndex);
3219
+ }
3220
+ }
3221
+ return {
3222
+ ...state,
3223
+ editingIndex: focusedIndex,
3224
+ editingType,
3225
+ editingValue: ''
3226
+ };
3227
+ };
3228
+
3229
+ // TODO much shared logic with newFolder
3230
+ const newFile = state => {
3231
+ return newDirent(state, CreateFile);
3232
+ };
3233
+
3234
+ const newFolder = state => {
3235
+ return newDirent(state, CreateFolder);
3236
+ };
3237
+
3158
3238
  const getContaingingFolder = (root, dirents, focusedIndex, pathSeparator) => {
3159
3239
  if (focusedIndex < 0) {
3160
3240
  return root;
@@ -3177,6 +3257,123 @@ const openContainingFolder = async state => {
3177
3257
  return state;
3178
3258
  };
3179
3259
 
3260
+ // TODO support multiselection and removing multiple dirents
3261
+ const removeDirent = async state => {
3262
+ if (state.focusedIndex < 0) {
3263
+ return state;
3264
+ }
3265
+ const dirent = getFocusedDirent$1(state);
3266
+ const absolutePath = dirent.path;
3267
+ try {
3268
+ // TODO handle error
3269
+ await remove(absolutePath);
3270
+ } catch (error) {
3271
+ // TODO vscode shows error as alert (no stacktrace) and retry button
3272
+ // maybe should show alert as well, but where to put stacktrace?
3273
+ // on web should probably show notification (dialog)
3274
+ // ErrorHandling.handleError(error)
3275
+ // await ErrorHandling.showErrorDialog(error)
3276
+ return;
3277
+ }
3278
+ // TODO avoid state mutation
3279
+ const newVersion = ++state.version;
3280
+ // TODO race condition
3281
+ // const newState = await loadContent(state:any)
3282
+ if (state.version !== newVersion || state.disposed) {
3283
+ return state;
3284
+ }
3285
+ // TODO is it possible to make this more functional instead of mutating state?
3286
+ // maybe every function returns a new state?
3287
+ const index = state.items.indexOf(dirent);
3288
+ let deleteEnd = index + 1;
3289
+ for (; deleteEnd < state.items.length; deleteEnd++) {
3290
+ if (state.items[deleteEnd].depth <= dirent.depth) {
3291
+ break;
3292
+ }
3293
+ }
3294
+ const deleteCount = deleteEnd - index;
3295
+ const newDirents = [...state.items];
3296
+ newDirents.splice(index, deleteCount);
3297
+ let indexToFocus = -1;
3298
+ if (newDirents.length === 0) {
3299
+ indexToFocus = -1;
3300
+ } else if (index < state.focusedIndex) {
3301
+ indexToFocus = state.focusedIndex - 1;
3302
+ } else if (index === state.focusedIndex) {
3303
+ indexToFocus = Math.max(state.focusedIndex - 1, 0);
3304
+ } else {
3305
+ indexToFocus = Math.max(state.focusedIndex - 1, 0);
3306
+ }
3307
+ return {
3308
+ ...state,
3309
+ items: newDirents,
3310
+ focusedIndex: indexToFocus
3311
+ };
3312
+ };
3313
+
3314
+ const renameDirent = state => {
3315
+ const {
3316
+ focusedIndex,
3317
+ items
3318
+ } = state;
3319
+ const item = items[focusedIndex];
3320
+ // Focus.setFocus(FocusKey.ExplorerEditBox)
3321
+ return {
3322
+ ...state,
3323
+ editingIndex: focusedIndex,
3324
+ editingType: Rename$1,
3325
+ editingValue: item.name
3326
+ };
3327
+ };
3328
+
3329
+ const getIconVirtualDom = (icon, type = Div) => {
3330
+ return {
3331
+ type,
3332
+ className: `MaskIcon MaskIcon${icon}`,
3333
+ role: None$2,
3334
+ childCount: 0
3335
+ };
3336
+ };
3337
+
3338
+ const getActionButtonVirtualDom = action => {
3339
+ const {
3340
+ id,
3341
+ icon,
3342
+ command
3343
+ } = action;
3344
+ return [{
3345
+ type: Button,
3346
+ className: IconButton,
3347
+ title: id,
3348
+ 'data-command': command,
3349
+ childCount: 1
3350
+ }, getIconVirtualDom(icon)];
3351
+ };
3352
+
3353
+ const getActionVirtualDom = action => {
3354
+ switch (action.type) {
3355
+ case Button$2:
3356
+ return getActionButtonVirtualDom(action);
3357
+ default:
3358
+ return [];
3359
+ }
3360
+ };
3361
+
3362
+ const getActionsVirtualDom = actions => {
3363
+ return [{
3364
+ type: Div,
3365
+ className: Actions,
3366
+ role: ToolBar,
3367
+ childCount: actions.length
3368
+ }, ...actions.flatMap(getActionVirtualDom)];
3369
+ };
3370
+
3371
+ const renderActions = state => {
3372
+ const actions = getActions(state.root);
3373
+ const dom = getActionsVirtualDom(actions);
3374
+ return dom;
3375
+ };
3376
+
3180
3377
  const getSavedRoot = (savedState, workspacePath) => {
3181
3378
  return workspacePath;
3182
3379
  };
@@ -3452,9 +3649,45 @@ const saveState = state => {
3452
3649
  };
3453
3650
  };
3454
3651
 
3652
+ const setDeltaY = (state, deltaY) => {
3653
+ const {
3654
+ itemHeight,
3655
+ height,
3656
+ items
3657
+ } = state;
3658
+ if (deltaY < 0) {
3659
+ deltaY = 0;
3660
+ } else if (deltaY > items.length * itemHeight - height) {
3661
+ deltaY = Math.max(items.length * itemHeight - height, 0);
3662
+ }
3663
+ if (state.deltaY === deltaY) {
3664
+ return state;
3665
+ }
3666
+ const minLineY = Math.round(deltaY / itemHeight);
3667
+ const maxLineY = minLineY + Math.round(height / itemHeight);
3668
+ return {
3669
+ ...state,
3670
+ deltaY,
3671
+ minLineY,
3672
+ maxLineY
3673
+ };
3674
+ };
3675
+
3676
+ const updateEditingValue = (state, value) => {
3677
+ const editingIcon = getFileIcon({
3678
+ name: value
3679
+ });
3680
+ return {
3681
+ ...state,
3682
+ editingValue: value,
3683
+ editingIcon
3684
+ };
3685
+ };
3686
+
3455
3687
  const commandMap = {
3456
3688
  'Explorer.acceptEdit': acceptEdit,
3457
3689
  'Explorer.cancelEdit': cancelEdit,
3690
+ 'Explorer.collapseAll': collapseAll$1,
3458
3691
  'Explorer.copyPath': copyPath$1,
3459
3692
  'Explorer.copyRelativePath': copyRelativePath$1,
3460
3693
  'Explorer.expandAll': expandAll,
@@ -3464,6 +3697,7 @@ const commandMap = {
3464
3697
  'Explorer.focusLast': focusLast,
3465
3698
  'Explorer.focusNext': focusNext,
3466
3699
  'Explorer.focusPrevious': focusPrevious,
3700
+ 'Explorer.getActions': getActions,
3467
3701
  'Explorer.getKeyBindings': getKeyBindings,
3468
3702
  'Explorer.getMenuEntries': getMenuEntries,
3469
3703
  'Explorer.getVirtualDom': getExplorerVirtualDom,
@@ -3476,18 +3710,25 @@ const commandMap = {
3476
3710
  'Explorer.handleClickCurrentButKeepFocus': handleClickCurrentButKeepFocus,
3477
3711
  'Explorer.handleClickOpenFolder': handleClickOpenFolder,
3478
3712
  'Explorer.handleContextMenu': handleContextMenu,
3713
+ 'Explorer.handleCopy': handleCopy,
3479
3714
  'Explorer.handleDrop': handleDrop,
3480
3715
  'Explorer.handleIconThemeChange': handleIconThemeChange,
3481
3716
  'Explorer.handlePaste': handlePaste,
3482
3717
  'Explorer.handlePointerDown': handlePointerDown,
3718
+ 'Explorer.handleUpload': handleUpload,
3483
3719
  'Explorer.handleWheel': handleWheel,
3484
3720
  'Explorer.loadContent': loadContent,
3721
+ 'Explorer.newFile': newFile,
3722
+ 'Explorer.newFolder': newFolder,
3485
3723
  'Explorer.openContainingFolder': openContainingFolder,
3486
3724
  'Explorer.removeDirent': removeDirent,
3487
3725
  'Explorer.renameDirent': renameDirent,
3726
+ 'Explorer.renderActions': renderActions,
3488
3727
  'Explorer.restoreState': restoreState,
3489
3728
  'Explorer.revealItem': revealItem,
3490
- 'Explorer.saveState': saveState
3729
+ 'Explorer.saveState': saveState,
3730
+ 'Explorer.setDeltaY': setDeltaY,
3731
+ 'Explorer.updateEditingValue': updateEditingValue
3491
3732
  };
3492
3733
 
3493
3734
  const listen = async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/explorer-view",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Explorer Worker",
5
5
  "main": "dist/explorerViewWorkerMain.js",
6
6
  "type": "module",