@lvce-editor/explorer-view 1.15.0 → 1.17.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.
@@ -898,7 +898,7 @@ const compareDirent = (direntA, direntB) => {
898
898
  return compareDirentType(direntA, direntB) || compareDirentName(direntA, direntB);
899
899
  };
900
900
 
901
- const getFileIcon$1 = ({
901
+ const getFileIcon = ({
902
902
  name
903
903
  }) => {
904
904
  return '';
@@ -921,7 +921,7 @@ const computeExplorerRenamedDirent = (dirents, index, newName) => {
921
921
  ...oldDirent,
922
922
  name: newName,
923
923
  path: oldDirent.path.slice(0, -oldDirent.name.length) + newName,
924
- icon: getFileIcon$1({
924
+ icon: getFileIcon({
925
925
  name: newName
926
926
  })
927
927
  };
@@ -1005,7 +1005,7 @@ const computeExplorerRenamedDirent = (dirents, index, newName) => {
1005
1005
  };
1006
1006
  };
1007
1007
 
1008
- const None$3 = 0;
1008
+ const None$5 = 0;
1009
1009
  const CreateFile = 1;
1010
1010
  const CreateFolder = 2;
1011
1011
  const Rename$1 = 3;
@@ -1155,7 +1155,7 @@ const acceptCreate = async (state, newDirentType, createFn) => {
1155
1155
  items: newDirents,
1156
1156
  editingIndex: -1,
1157
1157
  focusedIndex: insertIndex + 1,
1158
- editingType: None$3,
1158
+ editingType: None$5,
1159
1159
  maxLineY: newMaxlineY
1160
1160
  };
1161
1161
  };
@@ -1189,7 +1189,7 @@ const acceptRename = async state => {
1189
1189
  ...state,
1190
1190
  editingIndex: -1,
1191
1191
  editingValue: '',
1192
- editingType: None$3,
1192
+ editingType: None$5,
1193
1193
  editingIcon: '',
1194
1194
  focusedIndex,
1195
1195
  focused: true
@@ -1221,7 +1221,7 @@ const cancelEdit = state => {
1221
1221
  focused: true,
1222
1222
  editingIndex: -1,
1223
1223
  editingValue: '',
1224
- editingType: None$3
1224
+ editingType: None$5
1225
1225
  };
1226
1226
  };
1227
1227
 
@@ -1408,6 +1408,59 @@ const getExplorerMaxLineY = (minLineY, height, itemHeight, direntsLength) => {
1408
1408
  return maxLineY;
1409
1409
  };
1410
1410
 
1411
+ const getIconsCached = (dirents, fileIconCache) => {
1412
+ return dirents.map(dirent => fileIconCache[dirent.path]);
1413
+ };
1414
+
1415
+ const getMissingIconRequests = (dirents, fileIconCache) => {
1416
+ const missingRequests = [];
1417
+ for (const dirent of dirents) {
1418
+ if (!(dirent.path in fileIconCache)) {
1419
+ missingRequests.push({
1420
+ type: dirent.type,
1421
+ name: dirent.name,
1422
+ path: dirent.path
1423
+ });
1424
+ }
1425
+ }
1426
+ return missingRequests;
1427
+ };
1428
+
1429
+ const requestFileIcons = async requests => {
1430
+ const promises = requests.map(request => request.type === File ? invoke('IconTheme.getFileIcon', {
1431
+ name: request.name
1432
+ }) : invoke('IconTheme.getFolderIcon', {
1433
+ name: request.name
1434
+ }));
1435
+ return Promise.all(promises);
1436
+ };
1437
+
1438
+ const updateIconCache = (iconCache, missingRequests, newIcons) => {
1439
+ if (missingRequests.length === 0) {
1440
+ return iconCache;
1441
+ }
1442
+ const newFileIconCache = {
1443
+ ...iconCache
1444
+ };
1445
+ for (let i = 0; i < missingRequests.length; i++) {
1446
+ const request = missingRequests[i];
1447
+ const icon = newIcons[i];
1448
+ newFileIconCache[request.path] = icon;
1449
+ }
1450
+ return newFileIconCache;
1451
+ };
1452
+
1453
+ const getFileIcons = async (dirents, fileIconCache) => {
1454
+ const missingRequests = getMissingIconRequests(dirents, fileIconCache);
1455
+ const newIcons = await requestFileIcons(missingRequests);
1456
+ const newFileIconCache = updateIconCache(fileIconCache, missingRequests, newIcons);
1457
+ const icons = getIconsCached(dirents, newFileIconCache);
1458
+ return {
1459
+ icons,
1460
+ newFileIconCache
1461
+ };
1462
+ };
1463
+
1411
1464
  const expandAll = async state => {
1412
1465
  const {
1413
1466
  items,
@@ -1445,9 +1498,16 @@ const expandAll = async state => {
1445
1498
  }
1446
1499
  }
1447
1500
  const maxLineY = getExplorerMaxLineY(minLineY, height, itemHeight, newDirents.length);
1501
+ const visible = newDirents.slice(minLineY, maxLineY);
1502
+ const {
1503
+ icons,
1504
+ newFileIconCache
1505
+ } = await getFileIcons(visible, state.fileIconCache);
1448
1506
  return {
1449
1507
  ...state,
1450
1508
  items: newDirents,
1509
+ icons,
1510
+ fileIconCache: newFileIconCache,
1451
1511
  maxLineY
1452
1512
  };
1453
1513
  };
@@ -1740,20 +1800,24 @@ const getActions = root => {
1740
1800
  }];
1741
1801
  };
1742
1802
 
1743
- const None$2 = 'none';
1803
+ const None$4 = 'none';
1744
1804
  const ToolBar = 'toolbar';
1745
1805
  const Tree = 'tree';
1746
1806
  const TreeItem$1 = 'treeitem';
1747
1807
 
1748
1808
  const Actions = 'Actions';
1749
1809
  const Button$1 = 'Button';
1810
+ const ButtonNarrow = 'ButtonNarrow';
1750
1811
  const ButtonPrimary = 'ButtonPrimary';
1812
+ const ButtonWide = 'ButtonWide';
1751
1813
  const Chevron = 'Chevron';
1752
1814
  const Explorer$1 = 'Explorer';
1753
1815
  const FileIcon = 'FileIcon';
1754
1816
  const IconButton = 'IconButton';
1755
1817
  const InputBox = 'InputBox';
1756
1818
  const Label = 'Label';
1819
+ const MaskIconChevronDown = 'MaskIconChevronDown';
1820
+ const MaskIconChevronRight = 'MaskIconChevronRight';
1757
1821
  const TreeItem = 'TreeItem';
1758
1822
  const TreeItemActive = 'TreeItemActive';
1759
1823
  const Viewlet = 'Viewlet';
@@ -1764,6 +1828,7 @@ const HandleBlur = 'handleBlur';
1764
1828
  const HandleClick = 'handleClick';
1765
1829
  const handleClickOpenFolder$1 = 'handleClickOpenFolder';
1766
1830
  const HandleContextMenu = 'handleContextMenu';
1831
+ const HandleEditingInput = 'handleEditingInput';
1767
1832
  const HandleFocus = 'handleFocus';
1768
1833
  const HandlePointerDown = 'handlePointerDown';
1769
1834
  const HandleWheel = 'handleWheel';
@@ -1775,12 +1840,29 @@ const Text = 12;
1775
1840
  const Img = 17;
1776
1841
  const P = 50;
1777
1842
 
1843
+ const chevronDownVirtualDom = {
1844
+ type: Div,
1845
+ className: `${Chevron} ${MaskIconChevronDown}`,
1846
+ childCount: 0
1847
+ };
1848
+
1849
+ const chevronRightVirtualDom = {
1850
+ type: Div,
1851
+ className: `${Chevron} ${MaskIconChevronRight}`,
1852
+ childCount: 0
1853
+ };
1854
+
1855
+ const chevronDomNodes = [[], [chevronRightVirtualDom], [chevronDownVirtualDom]];
1856
+ const getChevronVirtualDom = chevronType => {
1857
+ return chevronDomNodes[chevronType];
1858
+ };
1859
+
1778
1860
  const getFileIconVirtualDom = icon => {
1779
1861
  return {
1780
1862
  type: Img,
1781
1863
  className: FileIcon,
1782
1864
  src: icon,
1783
- role: None$2,
1865
+ role: None$4,
1784
1866
  childCount: 0
1785
1867
  };
1786
1868
  };
@@ -1795,76 +1877,26 @@ const text = data => {
1795
1877
  };
1796
1878
  };
1797
1879
 
1798
- const getItemVirtualDomFile = item => {
1799
- const {
1800
- posInSet,
1801
- setSize,
1802
- icon,
1803
- name,
1804
- path,
1805
- depth,
1806
- isFocused,
1807
- isEditing,
1808
- indent
1809
- } = item;
1810
-
1811
- // TODO avoid mutation
1812
- const dom = [];
1813
- dom.push({
1814
- type: Div,
1815
- role: TreeItem$1,
1816
- className: TreeItem,
1817
- draggable: true,
1818
- title: path,
1819
- ariaPosInSet: posInSet,
1820
- ariaSetSize: setSize,
1821
- ariaLevel: depth,
1822
- childCount: 2,
1823
- paddingLeft: indent,
1824
- ariaLabel: name,
1825
- ariaDescription: ''
1826
- }, getFileIconVirtualDom(icon));
1880
+ const label = {
1881
+ type: Div,
1882
+ className: Label,
1883
+ childCount: 1
1884
+ };
1885
+ const getInputOrLabelDom = (isEditing, name) => {
1827
1886
  if (isEditing) {
1828
- dom.push({
1887
+ return [{
1829
1888
  type: Input,
1830
1889
  className: InputBox,
1831
1890
  id: 'ExplorerInput',
1832
- onInput: 'handleEditingInput',
1891
+ onInput: HandleEditingInput,
1833
1892
  childCount: 0,
1834
1893
  name: ExplorerInput
1835
- });
1836
- } else {
1837
- dom.push({
1838
- type: Div,
1839
- className: Label,
1840
- childCount: 1
1841
- }, text(name));
1894
+ }];
1842
1895
  }
1843
- if (isFocused) {
1844
- // @ts-ignore
1845
- dom[0].id = 'TreeItemActive';
1846
- // @ts-ignore
1847
- dom[0].className += ' ' + TreeItemActive;
1848
- }
1849
- return dom;
1850
- };
1851
-
1852
- const getChevronDownVirtualDom = () => {
1853
- return {
1854
- type: Div,
1855
- className: `${Chevron} MaskIconChevronDown`,
1856
- childCount: 0
1857
- };
1858
- };
1859
- const getChevronRightVirtualDom = () => {
1860
- return {
1861
- type: Div,
1862
- className: `${Chevron} MaskIconChevronRight`,
1863
- childCount: 0
1864
- };
1896
+ return [label, text(name)];
1865
1897
  };
1866
1898
 
1867
- const getItemVirtualDomFolder = item => {
1899
+ const getExplorerItemVirtualDom = item => {
1868
1900
  const {
1869
1901
  posInSet,
1870
1902
  setSize,
@@ -1872,76 +1904,33 @@ const getItemVirtualDomFolder = item => {
1872
1904
  name,
1873
1905
  path,
1874
1906
  depth,
1875
- type,
1876
- isFocused,
1877
- useChevrons,
1878
- indent
1907
+ indent,
1908
+ chevron,
1909
+ id,
1910
+ className,
1911
+ isEditing,
1912
+ ariaExpanded
1879
1913
  } = item;
1880
- let ariaExpanded = '';
1881
- let chevron;
1882
- switch (type) {
1883
- // TODO decide on directory vs folder
1884
- case Directory:
1885
- ariaExpanded = 'false';
1886
- chevron = getChevronRightVirtualDom();
1887
- break;
1888
- case DirectoryExpanding:
1889
- ariaExpanded = 'true'; // TODO tree should be aria-busy then
1890
- chevron = getChevronRightVirtualDom();
1891
- break;
1892
- case DirectoryExpanded:
1893
- ariaExpanded = 'true';
1894
- chevron = getChevronDownVirtualDom();
1895
- break;
1896
- }
1897
- const dom = [];
1898
- dom.push({
1914
+ const chevronDom = getChevronVirtualDom(chevron);
1915
+ const dom = [{
1899
1916
  type: Div,
1900
1917
  role: TreeItem$1,
1901
- className: TreeItem,
1918
+ className,
1902
1919
  draggable: true,
1903
1920
  title: path,
1904
1921
  ariaPosInSet: posInSet,
1905
1922
  ariaSetSize: setSize,
1906
1923
  ariaLevel: depth,
1907
- childCount: 2,
1924
+ childCount: 2 + chevronDom.length,
1908
1925
  paddingLeft: indent,
1909
1926
  ariaLabel: name,
1910
1927
  ariaExpanded,
1911
- ariaDescription: ''
1912
- });
1913
- if (useChevrons) {
1914
- // @ts-ignore
1915
- dom[0].childCount++;
1916
- // @ts-ignore
1917
- dom.push(chevron);
1918
- }
1919
- dom.push(getFileIconVirtualDom(icon), {
1920
- type: Div,
1921
- className: Label,
1922
- childCount: 1
1923
- }, text(name));
1924
- if (isFocused) {
1925
- // @ts-ignore
1926
- dom[0].id = 'TreeItemActive';
1927
- }
1928
+ ariaDescription: '',
1929
+ id
1930
+ }, ...chevronDom, getFileIconVirtualDom(icon), ...getInputOrLabelDom(isEditing, name)];
1928
1931
  return dom;
1929
1932
  };
1930
1933
 
1931
- const getExplorerItemVirtualDom = item => {
1932
- const {
1933
- type
1934
- } = item;
1935
- switch (type) {
1936
- case Directory:
1937
- case DirectoryExpanding:
1938
- case DirectoryExpanded:
1939
- return getItemVirtualDomFolder(item);
1940
- default:
1941
- return getItemVirtualDomFile(item);
1942
- }
1943
- };
1944
-
1945
1934
  const mergeClassNames = (...classNames) => {
1946
1935
  return classNames.filter(Boolean).join(' ');
1947
1936
  };
@@ -1962,7 +1951,7 @@ const getExplorerWelcomeVirtualDom = isWide => {
1962
1951
  childCount: 1
1963
1952
  }, text(youHaveNotYetOpenedAFolder()), {
1964
1953
  type: Button,
1965
- className: mergeClassNames(Button$1, ButtonPrimary, isWide ? 'ButtonWide' : 'ButtonNarrow'),
1954
+ className: mergeClassNames(Button$1, ButtonPrimary, isWide ? ButtonWide : ButtonNarrow),
1966
1955
  childCount: 1,
1967
1956
  onClick: handleClickOpenFolder$1
1968
1957
  }, text(openFolder$1())];
@@ -1972,9 +1961,7 @@ const getExplorerVirtualDom = (visibleItems, focusedIndex, root, isWide) => {
1972
1961
  if (!root) {
1973
1962
  return getExplorerWelcomeVirtualDom(isWide);
1974
1963
  }
1975
- // TODO
1976
- const dom = [];
1977
- dom.push({
1964
+ const dom = [{
1978
1965
  type: Div,
1979
1966
  className: mergeClassNames(Viewlet, Explorer$1),
1980
1967
  tabIndex: 0,
@@ -1988,8 +1975,7 @@ const getExplorerVirtualDom = (visibleItems, focusedIndex, root, isWide) => {
1988
1975
  onPointerDown: HandlePointerDown,
1989
1976
  onWheel: HandleWheel,
1990
1977
  onClick: HandleClick
1991
- });
1992
- dom.push(...visibleItems.flatMap(getExplorerItemVirtualDom));
1978
+ }, ...visibleItems.flatMap(getExplorerItemVirtualDom)];
1993
1979
  return dom;
1994
1980
  };
1995
1981
 
@@ -2091,7 +2077,7 @@ const getKeyBindings = () => {
2091
2077
  };
2092
2078
 
2093
2079
  const Separator = 1;
2094
- const None$1 = 0;
2080
+ const None$3 = 0;
2095
2081
  const RestoreFocus = 6;
2096
2082
 
2097
2083
  const menuEntrySeparator = {
@@ -2104,13 +2090,13 @@ const menuEntrySeparator = {
2104
2090
  const menuEntryNewFile = {
2105
2091
  id: 'newFile',
2106
2092
  label: newFile$1(),
2107
- flags: None$1,
2093
+ flags: None$3,
2108
2094
  command: 'Explorer.newFile'
2109
2095
  };
2110
2096
  const menuEntryNewFolder = {
2111
2097
  id: 'newFolder',
2112
2098
  label: newFolder$1(),
2113
- flags: None$1,
2099
+ flags: None$3,
2114
2100
  command: 'Explorer.newFolder'
2115
2101
  };
2116
2102
  const menuEntryOpenContainingFolder = {
@@ -2122,7 +2108,7 @@ const menuEntryOpenContainingFolder = {
2122
2108
  const menuEntryOpenInIntegratedTerminal = {
2123
2109
  id: 'openInIntegratedTerminal',
2124
2110
  label: openInIntegratedTerminal(),
2125
- flags: None$1,
2111
+ flags: None$3,
2126
2112
  command: /* TODO */-1
2127
2113
  };
2128
2114
  const menuEntryCut = {
@@ -2140,7 +2126,7 @@ const menuEntryCopy = {
2140
2126
  const menuEntryPaste = {
2141
2127
  id: 'paste',
2142
2128
  label: paste(),
2143
- flags: None$1,
2129
+ flags: None$3,
2144
2130
  command: 'Explorer.handlePaste'
2145
2131
  };
2146
2132
  const menuEntryCopyPath = {
@@ -2158,13 +2144,13 @@ const menuEntryCopyRelativePath = {
2158
2144
  const menuEntryRename = {
2159
2145
  id: 'rename',
2160
2146
  label: rename(),
2161
- flags: None$1,
2147
+ flags: None$3,
2162
2148
  command: 'Explorer.renameDirent'
2163
2149
  };
2164
2150
  const menuEntryDelete = {
2165
2151
  id: 'delete',
2166
2152
  label: deleteItem(),
2167
- flags: None$1,
2153
+ flags: None$3,
2168
2154
  command: 'Explorer.removeDirent'
2169
2155
  };
2170
2156
  const ALL_ENTRIES = [menuEntryNewFile, menuEntryNewFolder, menuEntryOpenContainingFolder, menuEntryOpenInIntegratedTerminal, menuEntrySeparator, menuEntryCut, menuEntryCopy, menuEntryPaste, menuEntrySeparator, menuEntryCopyPath, menuEntryCopyRelativePath, menuEntrySeparator, menuEntryRename, menuEntryDelete];
@@ -2205,51 +2191,98 @@ const getMenuEntries = state => {
2205
2191
  }
2206
2192
  };
2207
2193
 
2208
- const defaultIndent = 1;
2194
+ const None$2 = 0;
2195
+ const Right = 1;
2196
+ const Down = 2;
2197
+
2198
+ const getChevronType = (type, useChevrons) => {
2199
+ if (!useChevrons) {
2200
+ return None$2;
2201
+ }
2202
+ switch (type) {
2203
+ case Directory:
2204
+ return Right;
2205
+ case DirectoryExpanded:
2206
+ case DirectoryExpanding:
2207
+ return Down;
2208
+ default:
2209
+ return None$2;
2210
+ }
2211
+ };
2212
+
2213
+ const None$1 = 0;
2214
+ const Expanded = 1;
2215
+ const Collapsed = 2;
2216
+
2217
+ const getExpandedType = type => {
2218
+ switch (type) {
2219
+ case Directory:
2220
+ return Collapsed;
2221
+ case DirectoryExpanding:
2222
+ case DirectoryExpanded:
2223
+ return Expanded;
2224
+ default:
2225
+ return None$1;
2226
+ }
2227
+ };
2228
+
2229
+ const defaultIndent$1 = 1;
2209
2230
  const getTreeItemIndent = depth => {
2210
- // TODO logic should be in getVisibleItems
2211
- return `${depth * defaultIndent}rem`;
2231
+ return `${depth * defaultIndent$1}rem`;
2212
2232
  };
2213
2233
 
2234
+ // TODO make all of these variable configurable
2235
+ const defaultPaddingLeft = 4;
2236
+ const defaultIndent = 8;
2237
+
2238
+ // TODO make chevron size configurable
2239
+ const chevronSize = 22;
2240
+ const getTreeItemIndentWithChevron = (depth, chevron) => {
2241
+ // TODO use numeric value here, convert to string value in renderer process
2242
+ const extraSpace = chevron ? 0 : chevronSize;
2243
+ return `${depth * defaultIndent + extraSpace + defaultPaddingLeft}px`;
2244
+ };
2245
+
2246
+ const ariaExpandedValues = [undefined, 'true', 'false'];
2214
2247
  const getVisibleExplorerItems = (items, minLineY, maxLineY, focusedIndex, editingIndex, editingType, editingValue, icons, useChevrons) => {
2215
2248
  const visible = [];
2249
+ const indentFn = useChevrons ? getTreeItemIndentWithChevron : getTreeItemIndent;
2216
2250
  let iconIndex = 0;
2217
2251
  for (let i = minLineY; i < Math.min(maxLineY, items.length); i++) {
2218
2252
  const item = items[i];
2219
2253
  const icon = icons[iconIndex++];
2220
- const indent = getTreeItemIndent(item.depth);
2221
- if (i === editingIndex) {
2222
- visible.push({
2223
- ...item,
2224
- isFocused: i === focusedIndex,
2225
- isEditing: true,
2226
- icon,
2227
- useChevrons,
2228
- indent
2229
- });
2230
- } else {
2231
- visible.push({
2232
- ...item,
2233
- isFocused: i === focusedIndex,
2234
- icon,
2235
- useChevrons,
2236
- indent
2237
- });
2238
- }
2254
+ const chevron = getChevronType(item.type, useChevrons);
2255
+ const indent = indentFn(item.depth, chevron);
2256
+ const isFocused = i === focusedIndex;
2257
+ const id = isFocused ? 'TreeItemActive' : undefined;
2258
+ const className = isFocused ? TreeItem + ' ' + TreeItemActive : TreeItem;
2259
+ const expanded = getExpandedType(item.type);
2260
+ const ariaExpanded = ariaExpandedValues[expanded];
2261
+ visible.push({
2262
+ ...item,
2263
+ isEditing: i === editingIndex,
2264
+ icon,
2265
+ indent,
2266
+ ariaExpanded,
2267
+ chevron,
2268
+ id,
2269
+ className
2270
+ });
2239
2271
  }
2240
- if (editingType !== None$3 && editingIndex === -1) {
2272
+ if (editingType !== None$5 && editingIndex === -1) {
2241
2273
  visible.push({
2242
2274
  depth: 3,
2243
2275
  posInSet: 1,
2244
2276
  setSize: 1,
2245
2277
  icon: '',
2246
- isFocused: false,
2247
2278
  name: 'new',
2248
2279
  path: '/test/new',
2249
- type: 2,
2250
2280
  isEditing: true,
2251
- useChevrons,
2252
- indent: ''
2281
+ indent: '',
2282
+ ariaExpanded: undefined,
2283
+ chevron: 0,
2284
+ id: undefined,
2285
+ className: TreeItem
2253
2286
  });
2254
2287
  }
2255
2288
  return visible;
@@ -2261,7 +2294,7 @@ const handleBlur = state => {
2261
2294
  const {
2262
2295
  editingType
2263
2296
  } = state;
2264
- if (editingType !== None$3) {
2297
+ if (editingType !== None$5) {
2265
2298
  return state;
2266
2299
  }
2267
2300
  return {
@@ -2270,22 +2303,6 @@ const handleBlur = state => {
2270
2303
  };
2271
2304
  };
2272
2305
 
2273
- const getFileIcon = dirent => {
2274
- if (dirent.type === File) {
2275
- return invoke('IconTheme.getFileIcon', {
2276
- name: dirent.name
2277
- });
2278
- }
2279
- return invoke('IconTheme.getFolderIcon', {
2280
- name: dirent.name
2281
- });
2282
- };
2283
- const getFileIcons = async dirents => {
2284
- const promises = dirents.map(getFileIcon);
2285
- const icons = await Promise.all(promises);
2286
- return icons;
2287
- };
2288
-
2289
2306
  const handleClickDirectory = async (state, dirent, index, keepFocus) => {
2290
2307
  dirent.type = DirectoryExpanding;
2291
2308
  // TODO handle error
@@ -2312,11 +2329,15 @@ const handleClickDirectory = async (state, dirent, index, keepFocus) => {
2312
2329
  // TODO when focused index has changed while expanding, don't update it
2313
2330
  const maxLineY = getExplorerMaxLineY(minLineY, height, itemHeight, newDirents.length);
2314
2331
  const parts = newDirents.slice(minLineY, maxLineY);
2315
- const icons = await getFileIcons(parts);
2332
+ const {
2333
+ icons,
2334
+ newFileIconCache
2335
+ } = await getFileIcons(parts, state.fileIconCache);
2316
2336
  return {
2317
2337
  ...state,
2318
2338
  items: newDirents,
2319
2339
  icons,
2340
+ fileIconCache: newFileIconCache,
2320
2341
  focusedIndex: newIndex,
2321
2342
  focused: keepFocus,
2322
2343
  maxLineY
@@ -2343,11 +2364,15 @@ const handleClickDirectoryExpanded$1 = async (state, dirent, index, keepFocus) =
2343
2364
  const newMinLineY = newMaxLineY - visibleItems;
2344
2365
  const deltaY = newMinLineY * itemHeight;
2345
2366
  const parts = newDirents.slice(minLineY, maxLineY);
2346
- const icons = await getFileIcons(parts);
2367
+ const {
2368
+ icons,
2369
+ newFileIconCache
2370
+ } = await getFileIcons(parts, state.fileIconCache);
2347
2371
  return {
2348
2372
  ...state,
2349
2373
  items: newDirents,
2350
2374
  icons,
2375
+ fileIconCache: newFileIconCache,
2351
2376
  focusedIndex: index,
2352
2377
  focused: keepFocus,
2353
2378
  minLineY: newMinLineY,
@@ -2356,11 +2381,15 @@ const handleClickDirectoryExpanded$1 = async (state, dirent, index, keepFocus) =
2356
2381
  };
2357
2382
  }
2358
2383
  const parts = newDirents.slice(state.minLineY, state.maxLineY);
2359
- const icons = await getFileIcons(parts);
2384
+ const {
2385
+ icons,
2386
+ newFileIconCache
2387
+ } = await getFileIcons(parts, state.fileIconCache);
2360
2388
  return {
2361
2389
  ...state,
2362
2390
  items: newDirents,
2363
2391
  icons,
2392
+ fileIconCache: newFileIconCache,
2364
2393
  focusedIndex: index,
2365
2394
  focused: keepFocus
2366
2395
  };
@@ -3243,7 +3272,8 @@ const getSavedRoot$1 = (savedState, workspacePath) => {
3243
3272
  return workspacePath;
3244
3273
  };
3245
3274
  const loadContent = async (state, savedState) => {
3246
- const useChevrons = false;
3275
+ const useChevronsRaw = await invoke('Preferences.get', 'explorer.useChevrons');
3276
+ const useChevrons = Boolean(useChevronsRaw);
3247
3277
  const workspacePath = await getWorkspacePath();
3248
3278
  const root = getSavedRoot$1(savedState, workspacePath);
3249
3279
  // TODO path separator could be restored from saved state
@@ -3263,12 +3293,16 @@ const loadContent = async (state, savedState) => {
3263
3293
  deltaY = savedState.deltaY;
3264
3294
  }
3265
3295
  const maxLineY = getExplorerMaxLineY(minLineY, height, itemHeight, restoredDirents.length);
3266
- const icons = await getFileIcons(restoredDirents);
3296
+ const {
3297
+ icons,
3298
+ newFileIconCache
3299
+ } = await getFileIcons(restoredDirents, Object.create(null));
3267
3300
  return {
3268
3301
  ...state,
3269
3302
  root,
3270
3303
  items: restoredDirents,
3271
3304
  icons,
3305
+ fileIconCache: newFileIconCache,
3272
3306
  minLineY,
3273
3307
  deltaY,
3274
3308
  maxLineY,
@@ -3399,15 +3433,15 @@ const removeDirent = async state => {
3399
3433
  indexToFocus = Math.max(state.focusedIndex - 1, 0);
3400
3434
  }
3401
3435
  const visible = newDirents.slice(state.minLineY, state.maxLineY);
3402
- const icons = await getFileIcons(visible);
3403
- console.log({
3404
- icons
3405
- });
3436
+ const {
3437
+ icons,
3438
+ newFileIconCache
3439
+ } = await getFileIcons(visible, state.fileIconCache);
3406
3440
  return {
3407
3441
  ...state,
3408
3442
  items: newDirents,
3409
- // @ts-ignore
3410
3443
  icons,
3444
+ fileIconCache: newFileIconCache,
3411
3445
  focusedIndex: indexToFocus
3412
3446
  };
3413
3447
  };
@@ -3432,11 +3466,7 @@ const renderItems = {
3432
3466
  return JSON.stringify(oldState.items) === JSON.stringify(newState.items) && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.focusedIndex === newState.focusedIndex && oldState.editingIndex === newState.editingIndex && oldState.editingType === newState.editingType && oldState.editingValue === newState.editingValue && oldState.width === newState.width;
3433
3467
  },
3434
3468
  apply(oldState, newState) {
3435
- const visibleDirents = getVisibleExplorerItems(newState.items, newState.minLineY, newState.maxLineY, newState.focusedIndex, newState.editingIndex, newState.editingType, newState.editingValue,
3436
- // @ts-ignore
3437
- newState.icons,
3438
- // @ts-ignore
3439
- newState.useChevrons);
3469
+ const visibleDirents = getVisibleExplorerItems(newState.items, newState.minLineY, newState.maxLineY, newState.focusedIndex, newState.editingIndex, newState.editingType, newState.editingValue, newState.icons, newState.useChevrons);
3440
3470
  const isWide = newState.width > 450;
3441
3471
  const dom = getExplorerVirtualDom(visibleDirents, newState.focusedIndex, newState.root, isWide);
3442
3472
  return ['Viewlet.setDom2', dom];
@@ -3486,7 +3516,7 @@ const getIconVirtualDom = (icon, type = Div) => {
3486
3516
  return {
3487
3517
  type,
3488
3518
  className: `MaskIcon MaskIcon${icon}`,
3489
- role: None$2,
3519
+ role: None$4,
3490
3520
  childCount: 0
3491
3521
  };
3492
3522
  };
@@ -3831,7 +3861,7 @@ const setDeltaY = (state, deltaY) => {
3831
3861
  };
3832
3862
 
3833
3863
  const updateEditingValue = (state, value) => {
3834
- const editingIcon = getFileIcon$1({
3864
+ const editingIcon = getFileIcon({
3835
3865
  name: value
3836
3866
  });
3837
3867
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/explorer-view",
3
- "version": "1.15.0",
3
+ "version": "1.17.0",
4
4
  "description": "Explorer Worker",
5
5
  "main": "dist/explorerViewWorkerMain.js",
6
6
  "type": "module",