@lvce-editor/explorer-view 1.16.0 → 1.18.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
  };
@@ -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
  };
@@ -1747,13 +1807,18 @@ 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';
1816
+ const FocusOutline = 'FocusOutline';
1754
1817
  const IconButton = 'IconButton';
1755
1818
  const InputBox = 'InputBox';
1756
1819
  const Label = 'Label';
1820
+ const MaskIconChevronDown = 'MaskIconChevronDown';
1821
+ const MaskIconChevronRight = 'MaskIconChevronRight';
1757
1822
  const TreeItem = 'TreeItem';
1758
1823
  const TreeItemActive = 'TreeItemActive';
1759
1824
  const Viewlet = 'Viewlet';
@@ -1778,13 +1843,13 @@ const P = 50;
1778
1843
 
1779
1844
  const chevronDownVirtualDom = {
1780
1845
  type: Div,
1781
- className: `${Chevron} MaskIconChevronDown`,
1846
+ className: `${Chevron} ${MaskIconChevronDown}`,
1782
1847
  childCount: 0
1783
1848
  };
1784
1849
 
1785
1850
  const chevronRightVirtualDom = {
1786
1851
  type: Div,
1787
- className: `${Chevron} MaskIconChevronRight`,
1852
+ className: `${Chevron} ${MaskIconChevronRight}`,
1788
1853
  childCount: 0
1789
1854
  };
1790
1855
 
@@ -1887,19 +1952,20 @@ const getExplorerWelcomeVirtualDom = isWide => {
1887
1952
  childCount: 1
1888
1953
  }, text(youHaveNotYetOpenedAFolder()), {
1889
1954
  type: Button,
1890
- className: mergeClassNames(Button$1, ButtonPrimary, isWide ? 'ButtonWide' : 'ButtonNarrow'),
1955
+ className: mergeClassNames(Button$1, ButtonPrimary, isWide ? ButtonWide : ButtonNarrow),
1891
1956
  childCount: 1,
1892
1957
  onClick: handleClickOpenFolder$1
1893
1958
  }, text(openFolder$1())];
1894
1959
  };
1895
1960
 
1896
- const getExplorerVirtualDom = (visibleItems, focusedIndex, root, isWide) => {
1961
+ const getExplorerVirtualDom = (visibleItems, focusedIndex, root, isWide, focused) => {
1897
1962
  if (!root) {
1898
1963
  return getExplorerWelcomeVirtualDom(isWide);
1899
1964
  }
1965
+ const extraClass = focused && focusedIndex === -1 ? FocusOutline : '';
1900
1966
  const dom = [{
1901
1967
  type: Div,
1902
- className: mergeClassNames(Viewlet, Explorer$1),
1968
+ className: mergeClassNames(Viewlet, Explorer$1, extraClass),
1903
1969
  tabIndex: 0,
1904
1970
  role: Tree,
1905
1971
  ariaLabel: filesExplorer(),
@@ -2239,23 +2305,8 @@ const handleBlur = state => {
2239
2305
  };
2240
2306
  };
2241
2307
 
2242
- const getFileIcon = dirent => {
2243
- if (dirent.type === File) {
2244
- return invoke('IconTheme.getFileIcon', {
2245
- name: dirent.name
2246
- });
2247
- }
2248
- return invoke('IconTheme.getFolderIcon', {
2249
- name: dirent.name
2250
- });
2251
- };
2252
- const getFileIcons = async dirents => {
2253
- const promises = dirents.map(getFileIcon);
2254
- const icons = await Promise.all(promises);
2255
- return icons;
2256
- };
2257
-
2258
2308
  const handleClickDirectory = async (state, dirent, index, keepFocus) => {
2309
+ // @ts-ignore
2259
2310
  dirent.type = DirectoryExpanding;
2260
2311
  // TODO handle error
2261
2312
  const dirents = await getChildDirents(state.pathSeparator, dirent);
@@ -2271,7 +2322,9 @@ const handleClickDirectory = async (state, dirent, index, keepFocus) => {
2271
2322
  }
2272
2323
  const newDirents = [...state2.items];
2273
2324
  newDirents.splice(newIndex + 1, 0, ...dirents);
2325
+ // @ts-ignore
2274
2326
  dirent.type = DirectoryExpanded;
2327
+ // @ts-ignore
2275
2328
  dirent.icon = getIcon();
2276
2329
  const {
2277
2330
  height,
@@ -2281,11 +2334,15 @@ const handleClickDirectory = async (state, dirent, index, keepFocus) => {
2281
2334
  // TODO when focused index has changed while expanding, don't update it
2282
2335
  const maxLineY = getExplorerMaxLineY(minLineY, height, itemHeight, newDirents.length);
2283
2336
  const parts = newDirents.slice(minLineY, maxLineY);
2284
- const icons = await getFileIcons(parts);
2337
+ const {
2338
+ icons,
2339
+ newFileIconCache
2340
+ } = await getFileIcons(parts, state.fileIconCache);
2285
2341
  return {
2286
2342
  ...state,
2287
2343
  items: newDirents,
2288
2344
  icons,
2345
+ fileIconCache: newFileIconCache,
2289
2346
  focusedIndex: newIndex,
2290
2347
  focused: keepFocus,
2291
2348
  maxLineY
@@ -2296,9 +2353,12 @@ const handleClickDirectoryExpanded$1 = async (state, dirent, index, keepFocus) =
2296
2353
  const {
2297
2354
  minLineY,
2298
2355
  maxLineY,
2299
- itemHeight
2356
+ itemHeight,
2357
+ fileIconCache
2300
2358
  } = state;
2359
+ // @ts-ignore
2301
2360
  dirent.type = Directory;
2361
+ // @ts-ignore
2302
2362
  dirent.icon = getIcon();
2303
2363
  const endIndex = getParentEndIndex(state.items, index);
2304
2364
  const removeCount = endIndex - index - 1;
@@ -2312,11 +2372,15 @@ const handleClickDirectoryExpanded$1 = async (state, dirent, index, keepFocus) =
2312
2372
  const newMinLineY = newMaxLineY - visibleItems;
2313
2373
  const deltaY = newMinLineY * itemHeight;
2314
2374
  const parts = newDirents.slice(minLineY, maxLineY);
2315
- const icons = await getFileIcons(parts);
2375
+ const {
2376
+ icons,
2377
+ newFileIconCache
2378
+ } = await getFileIcons(parts, fileIconCache);
2316
2379
  return {
2317
2380
  ...state,
2318
2381
  items: newDirents,
2319
2382
  icons,
2383
+ fileIconCache: newFileIconCache,
2320
2384
  focusedIndex: index,
2321
2385
  focused: keepFocus,
2322
2386
  minLineY: newMinLineY,
@@ -2325,18 +2389,24 @@ const handleClickDirectoryExpanded$1 = async (state, dirent, index, keepFocus) =
2325
2389
  };
2326
2390
  }
2327
2391
  const parts = newDirents.slice(state.minLineY, state.maxLineY);
2328
- const icons = await getFileIcons(parts);
2392
+ const {
2393
+ icons,
2394
+ newFileIconCache
2395
+ } = await getFileIcons(parts, fileIconCache);
2329
2396
  return {
2330
2397
  ...state,
2331
2398
  items: newDirents,
2332
2399
  icons,
2400
+ fileIconCache: newFileIconCache,
2333
2401
  focusedIndex: index,
2334
2402
  focused: keepFocus
2335
2403
  };
2336
2404
  };
2337
2405
 
2338
2406
  const handleClickDirectoryExpanding = async (state, dirent, index, keepFocus) => {
2407
+ // @ts-ignore
2339
2408
  dirent.type = Directory;
2409
+ // @ts-ignore
2340
2410
  dirent.icon = getIcon();
2341
2411
  return {
2342
2412
  ...state,
@@ -2345,8 +2415,12 @@ const handleClickDirectoryExpanding = async (state, dirent, index, keepFocus) =>
2345
2415
  };
2346
2416
  };
2347
2417
 
2418
+ const openUri = async (uri, focus) => {
2419
+ await invoke(/* Main.openAbsolutePath */'Main.openUri', /* absolutePath */uri, /* focus */focus);
2420
+ };
2421
+
2348
2422
  const handleClickFile$1 = async (state, dirent, index, keepFocus = false) => {
2349
- await invoke(/* Main.openAbsolutePath */'Main.openUri', /* absolutePath */dirent.path, /* focus */!keepFocus);
2423
+ await openUri(dirent.path, !keepFocus);
2350
2424
  return {
2351
2425
  ...state,
2352
2426
  focusedIndex: index,
@@ -2924,6 +2998,15 @@ const handleDrop = async (state, x, y, files) => {
2924
2998
  }
2925
2999
  };
2926
3000
 
3001
+ const setFocus = key => {
3002
+ return invoke('Focus.setFocus', key);
3003
+ };
3004
+
3005
+ const handleFocus = async state => {
3006
+ await setFocus(FocusExplorer);
3007
+ return state;
3008
+ };
3009
+
2927
3010
  const updateIcon = dirent => {
2928
3011
  return {
2929
3012
  ...dirent,
@@ -3233,12 +3316,16 @@ const loadContent = async (state, savedState) => {
3233
3316
  deltaY = savedState.deltaY;
3234
3317
  }
3235
3318
  const maxLineY = getExplorerMaxLineY(minLineY, height, itemHeight, restoredDirents.length);
3236
- const icons = await getFileIcons(restoredDirents);
3319
+ const {
3320
+ icons,
3321
+ newFileIconCache
3322
+ } = await getFileIcons(restoredDirents, Object.create(null));
3237
3323
  return {
3238
3324
  ...state,
3239
3325
  root,
3240
3326
  items: restoredDirents,
3241
3327
  icons,
3328
+ fileIconCache: newFileIconCache,
3242
3329
  minLineY,
3243
3330
  deltaY,
3244
3331
  maxLineY,
@@ -3258,10 +3345,6 @@ const handleWorkspaceChange = async state => {
3258
3345
  return newState;
3259
3346
  };
3260
3347
 
3261
- const setFocus = key => {
3262
- return invoke('Focus.setFocus', key);
3263
- };
3264
-
3265
3348
  const ExplorerEditBox = FocusExplorerEditBox;
3266
3349
 
3267
3350
  const newDirent = async (state, editingType) => {
@@ -3369,15 +3452,15 @@ const removeDirent = async state => {
3369
3452
  indexToFocus = Math.max(state.focusedIndex - 1, 0);
3370
3453
  }
3371
3454
  const visible = newDirents.slice(state.minLineY, state.maxLineY);
3372
- const icons = await getFileIcons(visible);
3373
- console.log({
3374
- icons
3375
- });
3455
+ const {
3456
+ icons,
3457
+ newFileIconCache
3458
+ } = await getFileIcons(visible, state.fileIconCache);
3376
3459
  return {
3377
3460
  ...state,
3378
3461
  items: newDirents,
3379
- // @ts-ignore
3380
3462
  icons,
3463
+ fileIconCache: newFileIconCache,
3381
3464
  focusedIndex: indexToFocus
3382
3465
  };
3383
3466
  };
@@ -3399,21 +3482,22 @@ const renameDirent = state => {
3399
3482
 
3400
3483
  const renderItems = {
3401
3484
  isEqual(oldState, newState) {
3402
- 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;
3485
+ 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 && oldState.focused === newState.focused;
3403
3486
  },
3404
3487
  apply(oldState, newState) {
3405
3488
  const visibleDirents = getVisibleExplorerItems(newState.items, newState.minLineY, newState.maxLineY, newState.focusedIndex, newState.editingIndex, newState.editingType, newState.editingValue, newState.icons, newState.useChevrons);
3406
3489
  const isWide = newState.width > 450;
3407
- const dom = getExplorerVirtualDom(visibleDirents, newState.focusedIndex, newState.root, isWide);
3490
+ const dom = getExplorerVirtualDom(visibleDirents, newState.focusedIndex, newState.root, isWide, newState.focused);
3408
3491
  return ['Viewlet.setDom2', dom];
3409
3492
  }
3410
3493
  };
3411
3494
 
3412
- // const renderFocusedIndex = {
3413
- // isEqual(oldState:any, newState:any) {
3495
+ // TODO add virtual dom diffing so that focus is not lost when updating dom
3496
+ // const renderFocus = {
3497
+ // isEqual(oldState: any, newState: any) {
3414
3498
  // return oldState.focusedIndex === newState.focusedIndex && oldState.focused === newState.focused && oldState.minLineY === newState.minLineY
3415
3499
  // },
3416
- // apply(oldState:any, newState:any) {
3500
+ // apply(oldState: any, newState: any) {
3417
3501
  // const oldFocusedIndex = oldState.focusedIndex - oldState.minLineY
3418
3502
  // const newFocusedIndex = newState.focusedIndex - newState.minLineY
3419
3503
  // return [/* method */ 'setFocusedIndex', /* oldindex */ oldFocusedIndex, /* newIndex */ newFocusedIndex, /* focused */ newState.focused]
@@ -3796,8 +3880,12 @@ const setDeltaY = (state, deltaY) => {
3796
3880
  };
3797
3881
  };
3798
3882
 
3883
+ const terminate = () => {
3884
+ globalThis.close();
3885
+ };
3886
+
3799
3887
  const updateEditingValue = (state, value) => {
3800
- const editingIcon = getFileIcon$1({
3888
+ const editingIcon = getFileIcon({
3801
3889
  name: value
3802
3890
  });
3803
3891
  return {
@@ -3836,6 +3924,7 @@ const commandMap = {
3836
3924
  'Explorer.handleCopy': handleCopy,
3837
3925
  'Explorer.handleDragOver': handleDragOver,
3838
3926
  'Explorer.handleDrop': handleDrop,
3927
+ 'Explorer.handleFocus': handleFocus,
3839
3928
  'Explorer.handleIconThemeChange': handleIconThemeChange,
3840
3929
  'Explorer.handlePaste': handlePaste,
3841
3930
  'Explorer.handlePointerDown': handlePointerDown,
@@ -3854,6 +3943,7 @@ const commandMap = {
3854
3943
  'Explorer.revealItem': revealItem,
3855
3944
  'Explorer.saveState': saveState,
3856
3945
  'Explorer.setDeltaY': setDeltaY,
3946
+ 'Explorer.terminate': terminate,
3857
3947
  'Explorer.updateEditingValue': updateEditingValue,
3858
3948
  'Explorer.updateIcons': updateIcons
3859
3949
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/explorer-view",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "Explorer Worker",
5
5
  "main": "dist/explorerViewWorkerMain.js",
6
6
  "type": "module",