@lvce-editor/explorer-view 1.5.0 → 1.7.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 +497 -240
- package/package.json +1 -1
|
@@ -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
|
|
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
|
|
1583
|
-
const
|
|
1584
|
-
const
|
|
1585
|
-
const
|
|
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
|
-
|
|
1604
|
-
|
|
1605
|
-
const
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
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(
|
|
1660
|
+
return i18nString(OpenContainingFolder);
|
|
1633
1661
|
};
|
|
1634
1662
|
const openInIntegratedTerminal = () => {
|
|
1635
|
-
return i18nString(
|
|
1663
|
+
return i18nString(OpenInIntegratedTerminal);
|
|
1636
1664
|
};
|
|
1637
1665
|
const cut = () => {
|
|
1638
|
-
return i18nString(
|
|
1666
|
+
return i18nString(Cut$1);
|
|
1639
1667
|
};
|
|
1640
1668
|
const copy = () => {
|
|
1641
|
-
return i18nString(
|
|
1669
|
+
return i18nString(Copy$1);
|
|
1642
1670
|
};
|
|
1643
1671
|
const paste = () => {
|
|
1644
|
-
return i18nString(
|
|
1672
|
+
return i18nString(Paste);
|
|
1645
1673
|
};
|
|
1646
1674
|
const copyPath = () => {
|
|
1647
|
-
return i18nString(
|
|
1675
|
+
return i18nString(CopyPath);
|
|
1648
1676
|
};
|
|
1649
1677
|
const copyRelativePath = () => {
|
|
1650
|
-
return i18nString(
|
|
1678
|
+
return i18nString(CopyRelativePath);
|
|
1651
1679
|
};
|
|
1652
1680
|
const rename = () => {
|
|
1653
|
-
return i18nString(
|
|
1681
|
+
return i18nString(Rename);
|
|
1654
1682
|
};
|
|
1655
1683
|
const deleteItem = () => {
|
|
1656
|
-
return i18nString(
|
|
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(
|
|
1693
|
+
return i18nString(FilesExplorer);
|
|
1660
1694
|
};
|
|
1661
1695
|
const youHaveNotYetOpenedAFolder = () => {
|
|
1662
|
-
return i18nString(
|
|
1696
|
+
return i18nString(YouHaveNotYetOpenedAFolder);
|
|
1663
1697
|
};
|
|
1664
1698
|
const openFolder$1 = () => {
|
|
1665
|
-
return i18nString(
|
|
1699
|
+
return i18nString(OpenFolder);
|
|
1666
1700
|
};
|
|
1667
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
|
+
}];
|
|
1727
|
+
};
|
|
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
|
};
|
|
@@ -2125,36 +2213,11 @@ const handleBlur = state => {
|
|
|
2125
2213
|
};
|
|
2126
2214
|
};
|
|
2127
2215
|
|
|
2128
|
-
|
|
2129
|
-
// every thing else can be in a separate module <viewlet>.lazy.js
|
|
2130
|
-
// and <viewlet>.ipc.js
|
|
2131
|
-
|
|
2132
|
-
// viewlet: creating | refreshing | done | disposed
|
|
2133
|
-
// TODO recycle viewlets (maybe)
|
|
2134
|
-
|
|
2135
|
-
// TODO instead of root string, there should be a root dirent
|
|
2136
|
-
|
|
2137
|
-
// TODO rename dirents to items, then can use virtual list component directly
|
|
2138
|
-
|
|
2139
|
-
// TODO support multiselection and removing multiple dirents
|
|
2140
|
-
|
|
2141
|
-
// TODO use posInSet and setSize properties to compute more effectively
|
|
2142
|
-
|
|
2143
|
-
// TODO much shared logic with newFolder
|
|
2144
|
-
|
|
2145
|
-
const handleClickFile$1 = async (state, dirent, index, keepFocus = false) => {
|
|
2146
|
-
// await Command.execute(/* Main.openAbsolutePath */ 'Main.openUri', /* absolutePath */ dirent.path, /* focus */ !keepFocus)
|
|
2147
|
-
return {
|
|
2148
|
-
...state,
|
|
2149
|
-
focusedIndex: index,
|
|
2150
|
-
focused: keepFocus
|
|
2151
|
-
};
|
|
2152
|
-
};
|
|
2153
|
-
const handleClickDirectory$1 = async (state, dirent, index, keepFocus) => {
|
|
2216
|
+
const handleClickDirectory = async (state, dirent, index, keepFocus) => {
|
|
2154
2217
|
dirent.type = DirectoryExpanding;
|
|
2155
2218
|
// TODO handle error
|
|
2156
2219
|
const dirents = await getChildDirents(state.pathSeparator, dirent);
|
|
2157
|
-
const state2 =
|
|
2220
|
+
const state2 = state;
|
|
2158
2221
|
if (!state2) {
|
|
2159
2222
|
return state;
|
|
2160
2223
|
}
|
|
@@ -2183,15 +2246,7 @@ const handleClickDirectory$1 = async (state, dirent, index, keepFocus) => {
|
|
|
2183
2246
|
maxLineY
|
|
2184
2247
|
};
|
|
2185
2248
|
};
|
|
2186
|
-
|
|
2187
|
-
dirent.type = Directory;
|
|
2188
|
-
dirent.icon = getIcon();
|
|
2189
|
-
return {
|
|
2190
|
-
...state,
|
|
2191
|
-
focusedIndex: index,
|
|
2192
|
-
focused: keepFocus
|
|
2193
|
-
};
|
|
2194
|
-
};
|
|
2249
|
+
|
|
2195
2250
|
const handleClickDirectoryExpanded$1 = (state, dirent, index, keepFocus) => {
|
|
2196
2251
|
const {
|
|
2197
2252
|
minLineY,
|
|
@@ -2228,6 +2283,26 @@ const handleClickDirectoryExpanded$1 = (state, dirent, index, keepFocus) => {
|
|
|
2228
2283
|
focused: keepFocus
|
|
2229
2284
|
};
|
|
2230
2285
|
};
|
|
2286
|
+
|
|
2287
|
+
const handleClickDirectoryExpanding = (state, dirent, index, keepFocus) => {
|
|
2288
|
+
dirent.type = Directory;
|
|
2289
|
+
dirent.icon = getIcon();
|
|
2290
|
+
return {
|
|
2291
|
+
...state,
|
|
2292
|
+
focusedIndex: index,
|
|
2293
|
+
focused: keepFocus
|
|
2294
|
+
};
|
|
2295
|
+
};
|
|
2296
|
+
|
|
2297
|
+
const handleClickFile$1 = async (state, dirent, index, keepFocus = false) => {
|
|
2298
|
+
// await Command.execute(/* Main.openAbsolutePath */ 'Main.openUri', /* absolutePath */ dirent.path, /* focus */ !keepFocus)
|
|
2299
|
+
return {
|
|
2300
|
+
...state,
|
|
2301
|
+
focusedIndex: index,
|
|
2302
|
+
focused: keepFocus
|
|
2303
|
+
};
|
|
2304
|
+
};
|
|
2305
|
+
|
|
2231
2306
|
const handleClickSymLink$1 = async (state, dirent, index) => {
|
|
2232
2307
|
const realPath = await getRealPath(dirent.path);
|
|
2233
2308
|
const type = await stat(realPath);
|
|
@@ -2238,6 +2313,24 @@ const handleClickSymLink$1 = async (state, dirent, index) => {
|
|
|
2238
2313
|
throw new Error(`unsupported file type ${type}`);
|
|
2239
2314
|
}
|
|
2240
2315
|
};
|
|
2316
|
+
|
|
2317
|
+
// TODO viewlet should only have create and refresh functions
|
|
2318
|
+
// every thing else can be in a separate module <viewlet>.lazy.js
|
|
2319
|
+
// and <viewlet>.ipc.js
|
|
2320
|
+
|
|
2321
|
+
// viewlet: creating | refreshing | done | disposed
|
|
2322
|
+
// TODO recycle viewlets (maybe)
|
|
2323
|
+
|
|
2324
|
+
// TODO instead of root string, there should be a root dirent
|
|
2325
|
+
|
|
2326
|
+
// TODO rename dirents to items, then can use virtual list component directly
|
|
2327
|
+
|
|
2328
|
+
// TODO support multiselection and removing multiple dirents
|
|
2329
|
+
|
|
2330
|
+
// TODO use posInSet and setSize properties to compute more effectively
|
|
2331
|
+
|
|
2332
|
+
// TODO much shared logic with newFolder
|
|
2333
|
+
|
|
2241
2334
|
const getClickFn = direntType => {
|
|
2242
2335
|
switch (direntType) {
|
|
2243
2336
|
case File:
|
|
@@ -2245,7 +2338,7 @@ const getClickFn = direntType => {
|
|
|
2245
2338
|
return handleClickFile$1;
|
|
2246
2339
|
case Directory:
|
|
2247
2340
|
case SymLinkFolder:
|
|
2248
|
-
return handleClickDirectory
|
|
2341
|
+
return handleClickDirectory;
|
|
2249
2342
|
case DirectoryExpanding:
|
|
2250
2343
|
return handleClickDirectoryExpanding;
|
|
2251
2344
|
case DirectoryExpanded:
|
|
@@ -2291,10 +2384,6 @@ const getParentStartIndex = (dirents, index) => {
|
|
|
2291
2384
|
const Keyboard = -1;
|
|
2292
2385
|
const LeftClick = 0;
|
|
2293
2386
|
|
|
2294
|
-
const openFolder = async () => {
|
|
2295
|
-
// TODO
|
|
2296
|
-
};
|
|
2297
|
-
|
|
2298
2387
|
// TODO viewlet should only have create and refresh functions
|
|
2299
2388
|
// every thing else can be in a separate module <viewlet>.lazy.js
|
|
2300
2389
|
// and <viewlet>.ipc.js
|
|
@@ -2304,25 +2393,25 @@ const openFolder = async () => {
|
|
|
2304
2393
|
|
|
2305
2394
|
// TODO instead of root string, there should be a root dirent
|
|
2306
2395
|
|
|
2307
|
-
const updateIcon = dirent => {
|
|
2396
|
+
const updateIcon$1 = dirent => {
|
|
2308
2397
|
return {
|
|
2309
2398
|
...dirent,
|
|
2310
2399
|
icon: getIcon()
|
|
2311
2400
|
};
|
|
2312
2401
|
};
|
|
2313
|
-
const updateIcons = state => {
|
|
2314
|
-
const newDirents = state.items.map(updateIcon);
|
|
2402
|
+
const updateIcons$1 = state => {
|
|
2403
|
+
const newDirents = state.items.map(updateIcon$1);
|
|
2315
2404
|
return {
|
|
2316
2405
|
...state,
|
|
2317
2406
|
items: newDirents
|
|
2318
2407
|
};
|
|
2319
2408
|
};
|
|
2320
2409
|
const handleIconThemeChange = state => {
|
|
2321
|
-
return updateIcons(state);
|
|
2410
|
+
return updateIcons$1(state);
|
|
2322
2411
|
};
|
|
2323
2412
|
|
|
2324
2413
|
// TODO rename dirents to items, then can use virtual list component directly
|
|
2325
|
-
const setDeltaY = (state, deltaY) => {
|
|
2414
|
+
const setDeltaY$1 = (state, deltaY) => {
|
|
2326
2415
|
const {
|
|
2327
2416
|
itemHeight,
|
|
2328
2417
|
height,
|
|
@@ -2346,93 +2435,11 @@ const setDeltaY = (state, deltaY) => {
|
|
|
2346
2435
|
};
|
|
2347
2436
|
};
|
|
2348
2437
|
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
|
-
};
|
|
2438
|
+
return setDeltaY$1(state, state.deltaY + deltaY);
|
|
2418
2439
|
};
|
|
2419
2440
|
|
|
2420
2441
|
// TODO use posInSet and setSize properties to compute more effectively
|
|
2421
2442
|
|
|
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
2443
|
// TODO much shared logic with newFolder
|
|
2437
2444
|
|
|
2438
2445
|
const handleClickFile = async (state, dirent, index, keepFocus = false) => {
|
|
@@ -2443,39 +2450,6 @@ const handleClickFile = async (state, dirent, index, keepFocus = false) => {
|
|
|
2443
2450
|
focused: keepFocus
|
|
2444
2451
|
};
|
|
2445
2452
|
};
|
|
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
2453
|
const handleClickDirectoryExpanded = (state, dirent, index, keepFocus) => {
|
|
2480
2454
|
const {
|
|
2481
2455
|
minLineY,
|
|
@@ -2625,6 +2599,10 @@ const handleArrowLeft = state => {
|
|
|
2625
2599
|
|
|
2626
2600
|
// TODO maybe just insert items into explorer and refresh whole explorer
|
|
2627
2601
|
|
|
2602
|
+
const openFolder = async () => {
|
|
2603
|
+
// TODO
|
|
2604
|
+
};
|
|
2605
|
+
|
|
2628
2606
|
const handleClickOpenFolder = async state => {
|
|
2629
2607
|
await openFolder();
|
|
2630
2608
|
return state;
|
|
@@ -2671,6 +2649,21 @@ const handleContextMenu = (state, button, x, y) => {
|
|
|
2671
2649
|
}
|
|
2672
2650
|
};
|
|
2673
2651
|
|
|
2652
|
+
const handleCopy = async state => {
|
|
2653
|
+
// TODO handle multiple files
|
|
2654
|
+
// TODO if not file is selected, what happens?
|
|
2655
|
+
const dirent = getFocusedDirent$1(state);
|
|
2656
|
+
if (!dirent) {
|
|
2657
|
+
console.info('[ViewletExplorer/handleCopy] no dirent selected');
|
|
2658
|
+
return;
|
|
2659
|
+
}
|
|
2660
|
+
const absolutePath = dirent.path;
|
|
2661
|
+
// TODO handle copy error gracefully
|
|
2662
|
+
const files = [absolutePath];
|
|
2663
|
+
await writeNativeFiles('copy', files);
|
|
2664
|
+
return state;
|
|
2665
|
+
};
|
|
2666
|
+
|
|
2674
2667
|
const getFilePathElectron = async file => {
|
|
2675
2668
|
return invoke('GetFilePathElectron.getFilePathElectron', file);
|
|
2676
2669
|
};
|
|
@@ -2963,8 +2956,7 @@ const None = 'none';
|
|
|
2963
2956
|
const Copy = 'copy';
|
|
2964
2957
|
const Cut = 'cut';
|
|
2965
2958
|
|
|
2966
|
-
const
|
|
2967
|
-
const nativeFiles = await readNativeFiles();
|
|
2959
|
+
const getPasteHandler = type => {
|
|
2968
2960
|
// TODO detect cut/paste event, not sure if that is possible
|
|
2969
2961
|
// TODO check that pasted folder is not a parent folder of opened folder
|
|
2970
2962
|
// TODO support pasting multiple paths
|
|
@@ -2977,18 +2969,36 @@ const handlePaste = async state => {
|
|
|
2977
2969
|
// TODO but what if a file is currently selected? Then maybe the parent folder
|
|
2978
2970
|
// TODO but will it work if the folder is a symlink?
|
|
2979
2971
|
// TODO handle error gracefully when copy fails
|
|
2980
|
-
switch (
|
|
2972
|
+
switch (type) {
|
|
2981
2973
|
case None:
|
|
2982
|
-
return handlePasteNone
|
|
2974
|
+
return handlePasteNone;
|
|
2983
2975
|
case Copy:
|
|
2984
|
-
return handlePasteCopy
|
|
2976
|
+
return handlePasteCopy;
|
|
2985
2977
|
case Cut:
|
|
2986
|
-
return handlePasteCut
|
|
2978
|
+
return handlePasteCut;
|
|
2987
2979
|
default:
|
|
2988
|
-
throw new Error(`unexpected native paste type: ${
|
|
2980
|
+
throw new Error(`unexpected native paste type: ${type}`);
|
|
2989
2981
|
}
|
|
2990
2982
|
};
|
|
2991
2983
|
|
|
2984
|
+
const handlePaste = async state => {
|
|
2985
|
+
const nativeFiles = await readNativeFiles();
|
|
2986
|
+
// TODO detect cut/paste event, not sure if that is possible
|
|
2987
|
+
// TODO check that pasted folder is not a parent folder of opened folder
|
|
2988
|
+
// TODO support pasting multiple paths
|
|
2989
|
+
// TODO what happens when pasting multiple paths, but some of them error?
|
|
2990
|
+
// how many error messages should be shown? Should the operation be undone?
|
|
2991
|
+
// TODO what if it is a large folder and takes a long time to copy? Should show progress
|
|
2992
|
+
// TODO what if there is a permission error? Probably should show a modal to ask for permission
|
|
2993
|
+
// TODO if error is EEXISTS, just rename the copy (e.g. file-copy-1.txt, file-copy-2.txt)
|
|
2994
|
+
// TODO actual target should be selected folder
|
|
2995
|
+
// TODO but what if a file is currently selected? Then maybe the parent folder
|
|
2996
|
+
// TODO but will it work if the folder is a symlink?
|
|
2997
|
+
// TODO handle error gracefully when copy fails
|
|
2998
|
+
const fn = getPasteHandler(nativeFiles.type);
|
|
2999
|
+
return fn(state, nativeFiles);
|
|
3000
|
+
};
|
|
3001
|
+
|
|
2992
3002
|
const handlePointerDown = (state, button, x, y) => {
|
|
2993
3003
|
const index = getIndexFromPosition(state, x, y);
|
|
2994
3004
|
if (button === LeftClick && index === -1) {
|
|
@@ -3001,15 +3011,34 @@ const handlePointerDown = (state, button, x, y) => {
|
|
|
3001
3011
|
return state;
|
|
3002
3012
|
};
|
|
3003
3013
|
|
|
3004
|
-
const
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3014
|
+
const handleUpload = async (state, dirents) => {
|
|
3015
|
+
const {
|
|
3016
|
+
root,
|
|
3017
|
+
pathSeparator
|
|
3018
|
+
} = state;
|
|
3019
|
+
for (const dirent of dirents) {
|
|
3020
|
+
// TODO switch
|
|
3021
|
+
// TODO symlink might not be possible to be copied
|
|
3022
|
+
// TODO create folder if type is 2
|
|
3023
|
+
if (dirent.type === /* File */1) {
|
|
3024
|
+
// TODO reading text might be inefficient for binary files
|
|
3025
|
+
// but not sure how else to send them via jsonrpc
|
|
3026
|
+
const content = await dirent.file.text();
|
|
3027
|
+
const absolutePath = [root, dirent.file.name].join(pathSeparator);
|
|
3028
|
+
await writeFile(absolutePath, content);
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
};
|
|
3008
3032
|
|
|
3009
3033
|
const getWorkspacePath = () => {
|
|
3010
3034
|
return invoke('Workspace.getPath');
|
|
3011
3035
|
};
|
|
3012
3036
|
|
|
3037
|
+
const EmptyString = '';
|
|
3038
|
+
|
|
3039
|
+
const Fulfilled = 'fulfilled';
|
|
3040
|
+
const Rejected = 'rejected';
|
|
3041
|
+
|
|
3013
3042
|
// TODO viewlet should only have create and refresh functions
|
|
3014
3043
|
// every thing else can be in a separate module <viewlet>.lazy.js
|
|
3015
3044
|
// and <viewlet>.ipc.js
|
|
@@ -3155,6 +3184,55 @@ const loadContent = async (state, savedState) => {
|
|
|
3155
3184
|
};
|
|
3156
3185
|
};
|
|
3157
3186
|
|
|
3187
|
+
const handleWorkspaceChange = async state => {
|
|
3188
|
+
const newRoot = await getWorkspacePath();
|
|
3189
|
+
const state1 = {
|
|
3190
|
+
...state,
|
|
3191
|
+
root: newRoot
|
|
3192
|
+
};
|
|
3193
|
+
const newState = await loadContent(state1, undefined);
|
|
3194
|
+
return newState;
|
|
3195
|
+
};
|
|
3196
|
+
|
|
3197
|
+
const ExplorerEditBox = FocusExplorerEditBox;
|
|
3198
|
+
|
|
3199
|
+
const setFocus = key => {
|
|
3200
|
+
return invoke('Focus.setFocus', key);
|
|
3201
|
+
};
|
|
3202
|
+
|
|
3203
|
+
const newDirent = async (state, editingType) => {
|
|
3204
|
+
// TODO make focus functional instead of side effect
|
|
3205
|
+
await setFocus(ExplorerEditBox);
|
|
3206
|
+
// TODO do it like vscode, select position between folders and files
|
|
3207
|
+
const {
|
|
3208
|
+
focusedIndex,
|
|
3209
|
+
items
|
|
3210
|
+
} = state;
|
|
3211
|
+
if (focusedIndex >= 0) {
|
|
3212
|
+
const dirent = items[focusedIndex];
|
|
3213
|
+
if (dirent.type === Directory) {
|
|
3214
|
+
// TODO handle error
|
|
3215
|
+
// @ts-ignore
|
|
3216
|
+
await handleClickDirectory(state, dirent);
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
3219
|
+
return {
|
|
3220
|
+
...state,
|
|
3221
|
+
editingIndex: focusedIndex,
|
|
3222
|
+
editingType,
|
|
3223
|
+
editingValue: ''
|
|
3224
|
+
};
|
|
3225
|
+
};
|
|
3226
|
+
|
|
3227
|
+
// TODO much shared logic with newFolder
|
|
3228
|
+
const newFile = state => {
|
|
3229
|
+
return newDirent(state, CreateFile);
|
|
3230
|
+
};
|
|
3231
|
+
|
|
3232
|
+
const newFolder = state => {
|
|
3233
|
+
return newDirent(state, CreateFolder);
|
|
3234
|
+
};
|
|
3235
|
+
|
|
3158
3236
|
const getContaingingFolder = (root, dirents, focusedIndex, pathSeparator) => {
|
|
3159
3237
|
if (focusedIndex < 0) {
|
|
3160
3238
|
return root;
|
|
@@ -3177,9 +3255,127 @@ const openContainingFolder = async state => {
|
|
|
3177
3255
|
return state;
|
|
3178
3256
|
};
|
|
3179
3257
|
|
|
3258
|
+
// TODO support multiselection and removing multiple dirents
|
|
3259
|
+
const removeDirent = async state => {
|
|
3260
|
+
if (state.focusedIndex < 0) {
|
|
3261
|
+
return state;
|
|
3262
|
+
}
|
|
3263
|
+
const dirent = getFocusedDirent$1(state);
|
|
3264
|
+
const absolutePath = dirent.path;
|
|
3265
|
+
try {
|
|
3266
|
+
// TODO handle error
|
|
3267
|
+
await remove(absolutePath);
|
|
3268
|
+
} catch (error) {
|
|
3269
|
+
// TODO vscode shows error as alert (no stacktrace) and retry button
|
|
3270
|
+
// maybe should show alert as well, but where to put stacktrace?
|
|
3271
|
+
// on web should probably show notification (dialog)
|
|
3272
|
+
// ErrorHandling.handleError(error)
|
|
3273
|
+
// await ErrorHandling.showErrorDialog(error)
|
|
3274
|
+
return;
|
|
3275
|
+
}
|
|
3276
|
+
// TODO avoid state mutation
|
|
3277
|
+
const newVersion = ++state.version;
|
|
3278
|
+
// TODO race condition
|
|
3279
|
+
// const newState = await loadContent(state:any)
|
|
3280
|
+
if (state.version !== newVersion || state.disposed) {
|
|
3281
|
+
return state;
|
|
3282
|
+
}
|
|
3283
|
+
// TODO is it possible to make this more functional instead of mutating state?
|
|
3284
|
+
// maybe every function returns a new state?
|
|
3285
|
+
const index = state.items.indexOf(dirent);
|
|
3286
|
+
let deleteEnd = index + 1;
|
|
3287
|
+
for (; deleteEnd < state.items.length; deleteEnd++) {
|
|
3288
|
+
if (state.items[deleteEnd].depth <= dirent.depth) {
|
|
3289
|
+
break;
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
3292
|
+
const deleteCount = deleteEnd - index;
|
|
3293
|
+
const newDirents = [...state.items];
|
|
3294
|
+
newDirents.splice(index, deleteCount);
|
|
3295
|
+
let indexToFocus = -1;
|
|
3296
|
+
if (newDirents.length === 0) {
|
|
3297
|
+
indexToFocus = -1;
|
|
3298
|
+
} else if (index < state.focusedIndex) {
|
|
3299
|
+
indexToFocus = state.focusedIndex - 1;
|
|
3300
|
+
} else if (index === state.focusedIndex) {
|
|
3301
|
+
indexToFocus = Math.max(state.focusedIndex - 1, 0);
|
|
3302
|
+
} else {
|
|
3303
|
+
indexToFocus = Math.max(state.focusedIndex - 1, 0);
|
|
3304
|
+
}
|
|
3305
|
+
return {
|
|
3306
|
+
...state,
|
|
3307
|
+
items: newDirents,
|
|
3308
|
+
focusedIndex: indexToFocus
|
|
3309
|
+
};
|
|
3310
|
+
};
|
|
3311
|
+
|
|
3312
|
+
const renameDirent = state => {
|
|
3313
|
+
const {
|
|
3314
|
+
focusedIndex,
|
|
3315
|
+
items
|
|
3316
|
+
} = state;
|
|
3317
|
+
const item = items[focusedIndex];
|
|
3318
|
+
// Focus.setFocus(FocusKey.ExplorerEditBox)
|
|
3319
|
+
return {
|
|
3320
|
+
...state,
|
|
3321
|
+
editingIndex: focusedIndex,
|
|
3322
|
+
editingType: Rename$1,
|
|
3323
|
+
editingValue: item.name
|
|
3324
|
+
};
|
|
3325
|
+
};
|
|
3326
|
+
|
|
3327
|
+
const getIconVirtualDom = (icon, type = Div) => {
|
|
3328
|
+
return {
|
|
3329
|
+
type,
|
|
3330
|
+
className: `MaskIcon MaskIcon${icon}`,
|
|
3331
|
+
role: None$2,
|
|
3332
|
+
childCount: 0
|
|
3333
|
+
};
|
|
3334
|
+
};
|
|
3335
|
+
|
|
3336
|
+
const getActionButtonVirtualDom = action => {
|
|
3337
|
+
const {
|
|
3338
|
+
id,
|
|
3339
|
+
icon,
|
|
3340
|
+
command
|
|
3341
|
+
} = action;
|
|
3342
|
+
return [{
|
|
3343
|
+
type: Button,
|
|
3344
|
+
className: IconButton,
|
|
3345
|
+
title: id,
|
|
3346
|
+
'data-command': command,
|
|
3347
|
+
childCount: 1
|
|
3348
|
+
}, getIconVirtualDom(icon)];
|
|
3349
|
+
};
|
|
3350
|
+
|
|
3351
|
+
const getActionVirtualDom = action => {
|
|
3352
|
+
switch (action.type) {
|
|
3353
|
+
case Button$2:
|
|
3354
|
+
return getActionButtonVirtualDom(action);
|
|
3355
|
+
default:
|
|
3356
|
+
return [];
|
|
3357
|
+
}
|
|
3358
|
+
};
|
|
3359
|
+
|
|
3360
|
+
const getActionsVirtualDom = actions => {
|
|
3361
|
+
return [{
|
|
3362
|
+
type: Div,
|
|
3363
|
+
className: Actions,
|
|
3364
|
+
role: ToolBar,
|
|
3365
|
+
childCount: actions.length
|
|
3366
|
+
}, ...actions.flatMap(getActionVirtualDom)];
|
|
3367
|
+
};
|
|
3368
|
+
|
|
3369
|
+
const renderActions = state => {
|
|
3370
|
+
const actions = getActions(state.root);
|
|
3371
|
+
const dom = getActionsVirtualDom(actions);
|
|
3372
|
+
return dom;
|
|
3373
|
+
};
|
|
3374
|
+
|
|
3180
3375
|
const getSavedRoot = (savedState, workspacePath) => {
|
|
3181
3376
|
return workspacePath;
|
|
3182
3377
|
};
|
|
3378
|
+
|
|
3183
3379
|
const restoreState = savedState => {
|
|
3184
3380
|
if (!savedState) {
|
|
3185
3381
|
return {
|
|
@@ -3204,6 +3400,21 @@ const restoreState = savedState => {
|
|
|
3204
3400
|
};
|
|
3205
3401
|
};
|
|
3206
3402
|
|
|
3403
|
+
const updateIcon = dirent => {
|
|
3404
|
+
return {
|
|
3405
|
+
...dirent,
|
|
3406
|
+
icon: getIcon()
|
|
3407
|
+
};
|
|
3408
|
+
};
|
|
3409
|
+
|
|
3410
|
+
const updateIcons = state => {
|
|
3411
|
+
const newDirents = state.items.map(updateIcon);
|
|
3412
|
+
return {
|
|
3413
|
+
...state,
|
|
3414
|
+
items: newDirents
|
|
3415
|
+
};
|
|
3416
|
+
};
|
|
3417
|
+
|
|
3207
3418
|
const getIndex = (dirents, uri) => {
|
|
3208
3419
|
for (let i = 0; i < dirents.length; i++) {
|
|
3209
3420
|
const dirent = dirents[i];
|
|
@@ -3452,9 +3663,45 @@ const saveState = state => {
|
|
|
3452
3663
|
};
|
|
3453
3664
|
};
|
|
3454
3665
|
|
|
3666
|
+
const setDeltaY = (state, deltaY) => {
|
|
3667
|
+
const {
|
|
3668
|
+
itemHeight,
|
|
3669
|
+
height,
|
|
3670
|
+
items
|
|
3671
|
+
} = state;
|
|
3672
|
+
if (deltaY < 0) {
|
|
3673
|
+
deltaY = 0;
|
|
3674
|
+
} else if (deltaY > items.length * itemHeight - height) {
|
|
3675
|
+
deltaY = Math.max(items.length * itemHeight - height, 0);
|
|
3676
|
+
}
|
|
3677
|
+
if (state.deltaY === deltaY) {
|
|
3678
|
+
return state;
|
|
3679
|
+
}
|
|
3680
|
+
const minLineY = Math.round(deltaY / itemHeight);
|
|
3681
|
+
const maxLineY = minLineY + Math.round(height / itemHeight);
|
|
3682
|
+
return {
|
|
3683
|
+
...state,
|
|
3684
|
+
deltaY,
|
|
3685
|
+
minLineY,
|
|
3686
|
+
maxLineY
|
|
3687
|
+
};
|
|
3688
|
+
};
|
|
3689
|
+
|
|
3690
|
+
const updateEditingValue = (state, value) => {
|
|
3691
|
+
const editingIcon = getFileIcon({
|
|
3692
|
+
name: value
|
|
3693
|
+
});
|
|
3694
|
+
return {
|
|
3695
|
+
...state,
|
|
3696
|
+
editingValue: value,
|
|
3697
|
+
editingIcon
|
|
3698
|
+
};
|
|
3699
|
+
};
|
|
3700
|
+
|
|
3455
3701
|
const commandMap = {
|
|
3456
3702
|
'Explorer.acceptEdit': acceptEdit,
|
|
3457
3703
|
'Explorer.cancelEdit': cancelEdit,
|
|
3704
|
+
'Explorer.collapseAll': collapseAll$1,
|
|
3458
3705
|
'Explorer.copyPath': copyPath$1,
|
|
3459
3706
|
'Explorer.copyRelativePath': copyRelativePath$1,
|
|
3460
3707
|
'Explorer.expandAll': expandAll,
|
|
@@ -3464,6 +3711,7 @@ const commandMap = {
|
|
|
3464
3711
|
'Explorer.focusLast': focusLast,
|
|
3465
3712
|
'Explorer.focusNext': focusNext,
|
|
3466
3713
|
'Explorer.focusPrevious': focusPrevious,
|
|
3714
|
+
'Explorer.getActions': getActions,
|
|
3467
3715
|
'Explorer.getKeyBindings': getKeyBindings,
|
|
3468
3716
|
'Explorer.getMenuEntries': getMenuEntries,
|
|
3469
3717
|
'Explorer.getVirtualDom': getExplorerVirtualDom,
|
|
@@ -3476,18 +3724,27 @@ const commandMap = {
|
|
|
3476
3724
|
'Explorer.handleClickCurrentButKeepFocus': handleClickCurrentButKeepFocus,
|
|
3477
3725
|
'Explorer.handleClickOpenFolder': handleClickOpenFolder,
|
|
3478
3726
|
'Explorer.handleContextMenu': handleContextMenu,
|
|
3727
|
+
'Explorer.handleCopy': handleCopy,
|
|
3479
3728
|
'Explorer.handleDrop': handleDrop,
|
|
3480
3729
|
'Explorer.handleIconThemeChange': handleIconThemeChange,
|
|
3481
3730
|
'Explorer.handlePaste': handlePaste,
|
|
3482
3731
|
'Explorer.handlePointerDown': handlePointerDown,
|
|
3732
|
+
'Explorer.handleUpload': handleUpload,
|
|
3483
3733
|
'Explorer.handleWheel': handleWheel,
|
|
3734
|
+
'Explorer.handleWorkspaceChange': handleWorkspaceChange,
|
|
3484
3735
|
'Explorer.loadContent': loadContent,
|
|
3736
|
+
'Explorer.newFile': newFile,
|
|
3737
|
+
'Explorer.newFolder': newFolder,
|
|
3485
3738
|
'Explorer.openContainingFolder': openContainingFolder,
|
|
3486
3739
|
'Explorer.removeDirent': removeDirent,
|
|
3487
3740
|
'Explorer.renameDirent': renameDirent,
|
|
3741
|
+
'Explorer.renderActions': renderActions,
|
|
3488
3742
|
'Explorer.restoreState': restoreState,
|
|
3489
3743
|
'Explorer.revealItem': revealItem,
|
|
3490
|
-
'Explorer.saveState': saveState
|
|
3744
|
+
'Explorer.saveState': saveState,
|
|
3745
|
+
'Explorer.setDeltaY': setDeltaY,
|
|
3746
|
+
'Explorer.updateEditingValue': updateEditingValue,
|
|
3747
|
+
'Explorer.updateIcons': updateIcons
|
|
3491
3748
|
};
|
|
3492
3749
|
|
|
3493
3750
|
const listen = async () => {
|