@lvce-editor/text-search-view 1.17.3 → 1.19.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.
@@ -1026,6 +1026,34 @@ const listen$1 = async (module, options) => {
1026
1026
  return ipc;
1027
1027
  };
1028
1028
 
1029
+ const createSharedLazyRpc = factory => {
1030
+ let rpcPromise;
1031
+ const getOrCreate = () => {
1032
+ if (!rpcPromise) {
1033
+ rpcPromise = factory();
1034
+ }
1035
+ return rpcPromise;
1036
+ };
1037
+ return {
1038
+ async dispose() {
1039
+ const rpc = await getOrCreate();
1040
+ await rpc.dispose();
1041
+ },
1042
+ async invoke(method, ...params) {
1043
+ const rpc = await getOrCreate();
1044
+ return rpc.invoke(method, ...params);
1045
+ },
1046
+ async invokeAndTransfer(method, ...params) {
1047
+ const rpc = await getOrCreate();
1048
+ return rpc.invokeAndTransfer(method, ...params);
1049
+ },
1050
+ async send(method, ...params) {
1051
+ const rpc = await getOrCreate();
1052
+ rpc.send(method, ...params);
1053
+ }
1054
+ };
1055
+ };
1056
+
1029
1057
  const create$7 = async ({
1030
1058
  commandMap,
1031
1059
  isMessagePortOpen = true,
@@ -1061,34 +1089,6 @@ const create$6 = async ({
1061
1089
  });
1062
1090
  };
1063
1091
 
1064
- const createSharedLazyRpc = factory => {
1065
- let rpcPromise;
1066
- const getOrCreate = () => {
1067
- if (!rpcPromise) {
1068
- rpcPromise = factory();
1069
- }
1070
- return rpcPromise;
1071
- };
1072
- return {
1073
- async dispose() {
1074
- const rpc = await getOrCreate();
1075
- await rpc.dispose();
1076
- },
1077
- async invoke(method, ...params) {
1078
- const rpc = await getOrCreate();
1079
- return rpc.invoke(method, ...params);
1080
- },
1081
- async invokeAndTransfer(method, ...params) {
1082
- const rpc = await getOrCreate();
1083
- return rpc.invokeAndTransfer(method, ...params);
1084
- },
1085
- async send(method, ...params) {
1086
- const rpc = await getOrCreate();
1087
- rpc.send(method, ...params);
1088
- }
1089
- };
1090
- };
1091
-
1092
1092
  const create$5 = async ({
1093
1093
  commandMap,
1094
1094
  isMessagePortOpen,
@@ -1189,7 +1189,7 @@ const None$2 = 'none';
1189
1189
  const ScrollBar$1 = 'scrollbar';
1190
1190
  const Status = 'status';
1191
1191
  const ToolBar = 'toolbar';
1192
- const Tree$1 = 'tree';
1192
+ const Tree$2 = 'tree';
1193
1193
  const TreeItem$1 = 'treeitem';
1194
1194
 
1195
1195
  const Actions = 'Actions';
@@ -1206,7 +1206,7 @@ const HighlightInserted = 'HighlightInserted';
1206
1206
  const IconButton = 'IconButton';
1207
1207
  const IconButtonDisabled = 'IconButtonDisabled';
1208
1208
  const InputBox = 'InputBox';
1209
- const Label$1 = 'Label';
1209
+ const Label = 'Label';
1210
1210
  const List$1 = 'List';
1211
1211
  const MaskIcon = 'MaskIcon';
1212
1212
  const MaskIconBook = 'MaskIconBook';
@@ -1223,7 +1223,7 @@ const MultilineInputBox = 'MultilineInputBox';
1223
1223
  const ScrollBar = 'ScrollBar';
1224
1224
  const ScrollBarThumb = 'ScrollBarThumb';
1225
1225
  const ScrollBarVertical = 'ScrollBarVertical';
1226
- const Search$3 = 'Search';
1226
+ const Search$2 = 'Search';
1227
1227
  const SearchField = 'SearchField';
1228
1228
  const SearchFieldButton = 'SearchFieldButton';
1229
1229
  const SearchFieldButtonChecked = 'SearchFieldButtonChecked';
@@ -1244,7 +1244,7 @@ const SearchToggleButton = 'SearchToggleButton';
1244
1244
  const SearchToggleButtonExpanded = 'SearchToggleButtonExpanded';
1245
1245
  const SourceControlBadge = 'SourceControlBadge';
1246
1246
  const ToggleDetails = 'ToggleDetails';
1247
- const Tree = 'Tree';
1247
+ const Tree$1 = 'Tree';
1248
1248
  const TreeItem = 'TreeItem';
1249
1249
  const TreeItemActive = 'TreeItemActive';
1250
1250
  const TreeItems$1 = 'TreeItems';
@@ -1254,175 +1254,18 @@ const ViewletSearchMessageIndented = 'ViewletSearchMessageIndented';
1254
1254
 
1255
1255
  const File$2 = 7;
1256
1256
 
1257
- const Audio = 0;
1258
1257
  const Button$2 = 1;
1259
- const Col = 2;
1260
- const ColGroup = 3;
1261
1258
  const Div = 4;
1262
- const H1 = 5;
1263
1259
  const Input = 6;
1264
- const Kbd = 7;
1265
1260
  const Span = 8;
1266
- const Table = 9;
1267
- const TBody = 10;
1268
- const Td = 11;
1269
1261
  const Text = 12;
1270
- const Th = 13;
1271
- const THead = 14;
1272
- const Tr = 15;
1273
- const I = 16;
1274
1262
  const Img = 17;
1275
- const Root = 0;
1276
1263
  const Ins = 20;
1277
1264
  const Del = 21;
1278
- const H2 = 22;
1279
- const H3 = 23;
1280
1265
  const H4 = 24;
1281
- const H5 = 25;
1282
- const H6 = 26;
1283
- const Article = 27;
1284
- const Aside = 28;
1285
- const Footer = 29;
1286
- const Header = 30;
1287
- const Nav = 40;
1288
- const Section = 41;
1289
- const Search$2 = 42;
1290
- const Dd = 43;
1291
- const Dl = 44;
1292
- const Figcaption = 45;
1293
- const Figure = 46;
1294
- const Hr = 47;
1295
- const Li = 48;
1296
- const Ol = 49;
1297
- const P = 50;
1298
- const Pre = 51;
1299
- const A = 53;
1300
- const Abbr = 54;
1301
- const Br = 55;
1302
- const Cite = 56;
1303
- const Data = 57;
1304
- const Time = 58;
1305
- const Tfoot = 59;
1306
- const Ul = 60;
1307
- const Video = 61;
1308
1266
  const TextArea = 62;
1309
- const Select = 63;
1310
- const Option = 64;
1311
- const Code = 65;
1312
- const Label = 66;
1313
- const Dt = 67;
1314
- const Iframe = 68;
1315
- const Main = 69;
1316
- const Strong = 70;
1317
- const Em = 71;
1318
- const Style = 72;
1319
- const Html = 73;
1320
- const Head = 74;
1321
- const Title = 75;
1322
- const Meta = 76;
1323
- const Canvas = 77;
1324
- const Form = 78;
1325
- const BlockQuote = 79;
1326
- const Quote = 80;
1327
- const Circle = 81;
1328
- const Defs = 82;
1329
- const Ellipse = 83;
1330
- const G = 84;
1331
- const Line = 85;
1332
- const Path = 86;
1333
- const Polygon = 87;
1334
- const Polyline = 88;
1335
- const Rect = 89;
1336
- const Svg = 90;
1337
- const Use = 91;
1338
1267
  const Reference = 100;
1339
1268
 
1340
- const VirtualDomElements = {
1341
- __proto__: null,
1342
- A,
1343
- Abbr,
1344
- Article,
1345
- Aside,
1346
- Audio,
1347
- BlockQuote,
1348
- Br,
1349
- Button: Button$2,
1350
- Canvas,
1351
- Circle,
1352
- Cite,
1353
- Code,
1354
- Col,
1355
- ColGroup,
1356
- Data,
1357
- Dd,
1358
- Defs,
1359
- Del,
1360
- Div,
1361
- Dl,
1362
- Dt,
1363
- Ellipse,
1364
- Em,
1365
- Figcaption,
1366
- Figure,
1367
- Footer,
1368
- Form,
1369
- G,
1370
- H1,
1371
- H2,
1372
- H3,
1373
- H4,
1374
- H5,
1375
- H6,
1376
- Head,
1377
- Header,
1378
- Hr,
1379
- Html,
1380
- I,
1381
- Iframe,
1382
- Img,
1383
- Input,
1384
- Ins,
1385
- Kbd,
1386
- Label,
1387
- Li,
1388
- Line,
1389
- Main,
1390
- Meta,
1391
- Nav,
1392
- Ol,
1393
- Option,
1394
- P,
1395
- Path,
1396
- Polygon,
1397
- Polyline,
1398
- Pre,
1399
- Quote,
1400
- Rect,
1401
- Reference,
1402
- Root,
1403
- Search: Search$2,
1404
- Section,
1405
- Select,
1406
- Span,
1407
- Strong,
1408
- Style,
1409
- Svg,
1410
- TBody,
1411
- THead,
1412
- Table,
1413
- Td,
1414
- Text,
1415
- TextArea,
1416
- Tfoot,
1417
- Th,
1418
- Time,
1419
- Title,
1420
- Tr,
1421
- Ul,
1422
- Use,
1423
- Video
1424
- };
1425
-
1426
1269
  const Button$1 = 'event.button';
1427
1270
  const ClientX = 'event.clientX';
1428
1271
  const ClientY = 'event.clientY';
@@ -1444,7 +1287,7 @@ const None$1 = 0;
1444
1287
  const LeftClick = 0;
1445
1288
 
1446
1289
  const ClipBoardWorker = 3400;
1447
- const DialogWorker = 7014;
1290
+ const DialogWorker$1 = 7014;
1448
1291
  const IconThemeWorker = 7009;
1449
1292
  const RendererProcess = 1670;
1450
1293
  const RendererWorker = 1;
@@ -1456,6 +1299,7 @@ const Match$1 = 2;
1456
1299
 
1457
1300
  const FocusElementByName = 'Viewlet.focusElementByName';
1458
1301
  const SetCss = 'Viewlet.setCss';
1302
+ const SetDom2 = 'Viewlet.setDom2';
1459
1303
  const SetFocusContext = 'Viewlet.setFocusContext';
1460
1304
  const SetValueByName = 'Viewlet.setValueByName';
1461
1305
  const SetPatches = 'Viewlet.setPatches';
@@ -1491,7 +1335,17 @@ const readText$1 = async () => {
1491
1335
  const {
1492
1336
  invoke: invoke$6,
1493
1337
  set: set$7
1494
- } = create$3(DialogWorker);
1338
+ } = create$3(DialogWorker$1);
1339
+ const prompt$1 = async (message, options = {}) => {
1340
+ return invoke$6('ConfirmPrompt.prompt', message, options);
1341
+ };
1342
+
1343
+ const DialogWorker = {
1344
+ __proto__: null,
1345
+ invoke: invoke$6,
1346
+ prompt: prompt$1,
1347
+ set: set$7
1348
+ };
1495
1349
 
1496
1350
  const {
1497
1351
  invoke: invoke$5,
@@ -1509,15 +1363,20 @@ const {
1509
1363
 
1510
1364
  const {
1511
1365
  invoke: invoke$3,
1512
- invokeAndTransfer,
1513
1366
  set: set$4
1367
+ } = create$3(TextMeasurementWorker);
1368
+
1369
+ const {
1370
+ invoke: invoke$2,
1371
+ invokeAndTransfer,
1372
+ set: set$3
1514
1373
  } = create$3(RendererWorker);
1515
1374
  const showContextMenu2 = async (uid, menuId, x, y, args) => {
1516
1375
  number(uid);
1517
1376
  number(menuId);
1518
1377
  number(x);
1519
1378
  number(y);
1520
- await invoke$3('ContextMenu.show2', uid, menuId, x, y, args);
1379
+ await invoke$2('ContextMenu.show2', uid, menuId, x, y, args);
1521
1380
  };
1522
1381
  const sendMessagePortToClipBoardWorker$1 = async (port, rpcId) => {
1523
1382
  const command = 'ClipBoard.handleMessagePort';
@@ -1536,31 +1395,46 @@ const sendMessagePortToIconThemeWorker = async (port, rpcId) => {
1536
1395
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToIconThemeWorker', port, command, rpcId);
1537
1396
  };
1538
1397
  const handleWorkspaceRefresh = async () => {
1539
- return invoke$3('Layout.handleWorkspaceRefresh');
1398
+ return invoke$2('Layout.handleWorkspaceRefresh');
1540
1399
  };
1541
1400
  const sendMessagePortToTextMeasurementWorker = async port => {
1542
1401
  const command = 'TextMeasurement.handleMessagePort';
1543
1402
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToTextMeasurementWorker', port, command, 0);
1544
1403
  };
1545
1404
  const getPreference = async key => {
1546
- return await invoke$3('Preferences.get', key);
1405
+ return await invoke$2('Preferences.get', key);
1547
1406
  };
1548
1407
  const openUri$1 = async (uri, focus, options) => {
1549
- await invoke$3('Main.openUri', uri, focus, options);
1408
+ await invoke$2('Main.openUri', {
1409
+ ...options,
1410
+ focus,
1411
+ uri
1412
+ });
1413
+ };
1414
+ const openUri2 = async ({
1415
+ focus,
1416
+ selections,
1417
+ uri
1418
+ }) => {
1419
+ await invoke$2('Main.openUri', {
1420
+ focus,
1421
+ selections,
1422
+ uri
1423
+ });
1550
1424
  };
1551
1425
 
1552
1426
  const {
1553
- invoke: invoke$2,
1554
- set: set$3
1427
+ invoke: invoke$1,
1428
+ set: set$2
1555
1429
  } = create$3(TextSearchWorker);
1556
1430
  const getIncrementalResults = async (searchId, minLineY, maxLineY) => {
1557
- return invoke$2('TextSearch.getIncrementalResults', searchId, minLineY, maxLineY);
1431
+ return invoke$1('TextSearch.getIncrementalResults', searchId, minLineY, maxLineY);
1558
1432
  };
1559
1433
  const search$1 = async (...args) => {
1560
- return invoke$2('TextSearch.search', ...args);
1434
+ return invoke$1('TextSearch.search', ...args);
1561
1435
  };
1562
1436
  const searchIncremental = async (...args) => {
1563
- return invoke$2('TextSearch.searchIncremental', ...args);
1437
+ return invoke$1('TextSearch.searchIncremental', ...args);
1564
1438
  };
1565
1439
 
1566
1440
  const toCommandId = key => {
@@ -1571,7 +1445,8 @@ const create$2 = () => {
1571
1445
  const commandQueues = new Map();
1572
1446
  const generations = Object.create(null);
1573
1447
  const states = Object.create(null);
1574
- const commandMapRef = {};
1448
+ const commandMapRef = Object.create(null);
1449
+ const commandsById = Object.create(null);
1575
1450
  const getGeneration = uid => generations[uid] || 0;
1576
1451
  const isCurrentGeneration = (uid, generation) => {
1577
1452
  return states[uid] !== undefined && getGeneration(uid) === generation;
@@ -1633,6 +1508,18 @@ const create$2 = () => {
1633
1508
  delete states[key];
1634
1509
  }
1635
1510
  },
1511
+ createDirectEventCommandMap(requestRender) {
1512
+ return {
1513
+ async 'Viewlet.executeViewletCommand'(uid, command, ...args) {
1514
+ const fn = commandsById[command];
1515
+ if (!fn) {
1516
+ throw new Error(`Viewlet command not found: ${command}`);
1517
+ }
1518
+ await fn(uid, ...args);
1519
+ await requestRender(uid);
1520
+ }
1521
+ };
1522
+ },
1636
1523
  diff(uid, modules, numbers) {
1637
1524
  const {
1638
1525
  oldState,
@@ -1664,6 +1551,9 @@ const create$2 = () => {
1664
1551
  },
1665
1552
  registerCommands(commandMap) {
1666
1553
  Object.assign(commandMapRef, commandMap);
1554
+ for (const [key, fn] of Object.entries(commandMap)) {
1555
+ commandsById[toCommandId(key)] = fn;
1556
+ }
1667
1557
  },
1668
1558
  set(uid, oldState, newState, scheduledState) {
1669
1559
  const current = states[uid];
@@ -1821,8 +1711,6 @@ const text = data => {
1821
1711
  };
1822
1712
  };
1823
1713
 
1824
- new Set(Object.values(VirtualDomElements));
1825
-
1826
1714
  const SetText = 1;
1827
1715
  const Replace$1 = 2;
1828
1716
  const SetAttribute = 3;
@@ -1833,6 +1721,7 @@ const NavigateParent = 8;
1833
1721
  const RemoveChild = 9;
1834
1722
  const NavigateSibling = 10;
1835
1723
  const SetReferenceNodeUid = 11;
1724
+ const MultiNavigation = 18;
1836
1725
 
1837
1726
  const isKey = key => {
1838
1727
  return key !== 'type' && key !== 'childCount';
@@ -1893,6 +1782,55 @@ const getChildrenWithCount = (nodes, startIndex, childCount) => {
1893
1782
  };
1894
1783
  };
1895
1784
 
1785
+ const isNavigationPatch = patch => {
1786
+ switch (patch.type) {
1787
+ case NavigateChild:
1788
+ case NavigateParent:
1789
+ case NavigateSibling:
1790
+ return true;
1791
+ default:
1792
+ return false;
1793
+ }
1794
+ };
1795
+ const getNavigationIndex = patch => {
1796
+ switch (patch.type) {
1797
+ case NavigateChild:
1798
+ case NavigateSibling:
1799
+ return patch.index;
1800
+ default:
1801
+ return 0;
1802
+ }
1803
+ };
1804
+ const appendNavigationPatch = (patches, type, index) => {
1805
+ const previousPatch = patches.at(-1);
1806
+ if (!previousPatch) {
1807
+ patches.push(type === NavigateParent ? {
1808
+ type
1809
+ } : {
1810
+ index,
1811
+ type
1812
+ });
1813
+ return;
1814
+ }
1815
+ if (previousPatch.type === MultiNavigation) {
1816
+ previousPatch.navigations.push(type, index);
1817
+ return;
1818
+ }
1819
+ if (isNavigationPatch(previousPatch)) {
1820
+ patches[patches.length - 1] = {
1821
+ navigations: [previousPatch.type, getNavigationIndex(previousPatch), type, index],
1822
+ type: MultiNavigation
1823
+ };
1824
+ return;
1825
+ }
1826
+ patches.push(type === NavigateParent ? {
1827
+ type
1828
+ } : {
1829
+ index,
1830
+ type
1831
+ });
1832
+ };
1833
+
1896
1834
  const compareNodes = (oldNode, newNode) => {
1897
1835
  // Check if node type changed - return null to signal incompatible nodes
1898
1836
  // (caller should handle this with a Replace operation)
@@ -1901,14 +1839,11 @@ const compareNodes = (oldNode, newNode) => {
1901
1839
  }
1902
1840
  const patches = [];
1903
1841
  // Handle reference nodes - special handling for uid changes
1904
- if (oldNode.type === Reference) {
1905
- if (oldNode.uid !== newNode.uid) {
1906
- patches.push({
1907
- type: SetReferenceNodeUid,
1908
- uid: newNode.uid
1909
- });
1910
- }
1911
- return patches;
1842
+ if (oldNode.type === Reference && oldNode.uid !== newNode.uid) {
1843
+ patches.push({
1844
+ type: SetReferenceNodeUid,
1845
+ uid: newNode.uid
1846
+ });
1912
1847
  }
1913
1848
  // Handle text nodes
1914
1849
  if (oldNode.type === Text && newNode.type === Text) {
@@ -1921,8 +1856,8 @@ const compareNodes = (oldNode, newNode) => {
1921
1856
  return patches;
1922
1857
  }
1923
1858
  // Compare attributes
1924
- const oldKeys = getKeys(oldNode);
1925
- const newKeys = getKeys(newNode);
1859
+ const oldKeys = getKeys(oldNode).filter(key => oldNode.type !== Reference || key !== 'uid');
1860
+ const newKeys = getKeys(newNode).filter(key => newNode.type !== Reference || key !== 'uid');
1926
1861
  // Check for attribute changes
1927
1862
  for (const key of newKeys) {
1928
1863
  if (oldNode[key] !== newNode[key]) {
@@ -1946,34 +1881,31 @@ const compareNodes = (oldNode, newNode) => {
1946
1881
  };
1947
1882
 
1948
1883
  const treeToArray = node => {
1949
- const result = [node.node];
1950
- for (const child of node.children) {
1951
- result.push(...treeToArray(child));
1884
+ const result = [];
1885
+ const stack = [node];
1886
+ while (stack.length > 0) {
1887
+ const current = stack.pop();
1888
+ result.push(current.node);
1889
+ for (let i = current.children.length - 1; i >= 0; i--) {
1890
+ stack.push(current.children[i]);
1891
+ }
1952
1892
  }
1953
1893
  return result;
1954
1894
  };
1955
1895
 
1956
1896
  const navigateToChild = (patches, currentChildIndex, index) => {
1957
1897
  if (currentChildIndex === -1) {
1958
- patches.push({
1959
- type: NavigateChild,
1960
- index
1961
- });
1898
+ appendNavigationPatch(patches, NavigateChild, index);
1962
1899
  return index;
1963
1900
  }
1964
1901
  if (currentChildIndex !== index) {
1965
- patches.push({
1966
- type: NavigateSibling,
1967
- index
1968
- });
1902
+ appendNavigationPatch(patches, NavigateSibling, index);
1969
1903
  }
1970
1904
  return index;
1971
1905
  };
1972
1906
  const navigateToParent = (patches, currentChildIndex) => {
1973
1907
  if (currentChildIndex >= 0) {
1974
- patches.push({
1975
- type: NavigateParent
1976
- });
1908
+ appendNavigationPatch(patches, NavigateParent, 0);
1977
1909
  }
1978
1910
  return -1;
1979
1911
  };
@@ -1989,6 +1921,29 @@ const replaceTree = (newNode, patches) => {
1989
1921
  nodes: treeToArray(newNode)
1990
1922
  });
1991
1923
  };
1924
+ const appendPatch = (patches, patch) => {
1925
+ switch (patch.type) {
1926
+ case MultiNavigation:
1927
+ for (let i = 0; i < patch.navigations.length; i += 2) {
1928
+ appendNavigationPatch(patches, patch.navigations[i], patch.navigations[i + 1]);
1929
+ }
1930
+ return;
1931
+ case NavigateChild:
1932
+ case NavigateSibling:
1933
+ appendNavigationPatch(patches, patch.type, patch.index);
1934
+ return;
1935
+ case NavigateParent:
1936
+ appendNavigationPatch(patches, patch.type, 0);
1937
+ return;
1938
+ default:
1939
+ patches.push(patch);
1940
+ }
1941
+ };
1942
+ const appendPatches = (patches, newPatches) => {
1943
+ for (const patch of newPatches) {
1944
+ appendPatch(patches, patch);
1945
+ }
1946
+ };
1992
1947
  const diffExistingChild = (oldNode, newNode, patches, currentChildIndex, index) => {
1993
1948
  const nodePatches = compareNodes(oldNode.node, newNode.node);
1994
1949
  if (nodePatches === null) {
@@ -1997,16 +1952,16 @@ const diffExistingChild = (oldNode, newNode, patches, currentChildIndex, index)
1997
1952
  return nextChildIndex;
1998
1953
  }
1999
1954
  const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
2000
- if (nodePatches.length === 0 && !hasChildrenToCompare) {
1955
+ const childPatches = [];
1956
+ if (hasChildrenToCompare) {
1957
+ diffChildren(oldNode.children, newNode.children, childPatches);
1958
+ }
1959
+ if (nodePatches.length === 0 && childPatches.length === 0) {
2001
1960
  return currentChildIndex;
2002
1961
  }
2003
1962
  const nextChildIndex = navigateToChild(patches, currentChildIndex, index);
2004
- if (nodePatches.length > 0) {
2005
- patches.push(...nodePatches);
2006
- }
2007
- if (hasChildrenToCompare) {
2008
- diffChildren(oldNode.children, newNode.children, patches);
2009
- }
1963
+ patches.push(...nodePatches);
1964
+ appendPatches(patches, childPatches);
2010
1965
  return nextChildIndex;
2011
1966
  };
2012
1967
  const diffRootNode = (oldNode, newNode, patches) => {
@@ -2062,7 +2017,7 @@ const diffTrees = (oldTree, newTree, patches, path) => {
2062
2017
  const removeTrailingNavigationPatches = patches => {
2063
2018
  while (patches.length > 0) {
2064
2019
  const patch = patches.at(-1);
2065
- if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) {
2020
+ if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling && patch.type !== MultiNavigation) {
2066
2021
  break;
2067
2022
  }
2068
2023
  patches.pop();
@@ -2112,6 +2067,95 @@ const clearSearchResults$1 = state => {
2112
2067
  };
2113
2068
  };
2114
2069
 
2070
+ const clamp$1 = (num, min, max) => {
2071
+ return Math.min(Math.max(num, min), max);
2072
+ };
2073
+
2074
+ const File = 1;
2075
+ const Match = 2;
2076
+ const Context = 3;
2077
+
2078
+ const getFilteredResults = (results, collapsedPaths) => {
2079
+ if (collapsedPaths.length === 0) {
2080
+ return results;
2081
+ }
2082
+ const filteredResults = [];
2083
+ let collapsedDepth = -1;
2084
+ for (const result of results) {
2085
+ const depth = result.depth ?? (result.type === File ? 0 : 1);
2086
+ if (collapsedDepth !== -1) {
2087
+ if (depth > collapsedDepth) {
2088
+ continue;
2089
+ }
2090
+ collapsedDepth = -1;
2091
+ }
2092
+ filteredResults.push(result);
2093
+ if (result.type === File && collapsedPaths.includes(result.text)) {
2094
+ collapsedDepth = depth;
2095
+ }
2096
+ }
2097
+ return filteredResults;
2098
+ };
2099
+
2100
+ // TODO optimize this function to return the minimum number
2101
+ // of visible items needed, e.g. when not scrolled 5 items with
2102
+ // 20px fill 100px but when scrolled 6 items are needed
2103
+ const getNumberOfVisibleItems$1 = (listHeight, itemHeight) => {
2104
+ return Math.ceil(listHeight / itemHeight) + 1;
2105
+ };
2106
+
2107
+ const getTreeListItems = results => {
2108
+ const listItems = [];
2109
+ const directories = new Set();
2110
+ let matchDepth = 0;
2111
+ for (const result of results) {
2112
+ if (result.type !== File) {
2113
+ listItems.push({
2114
+ ...result,
2115
+ depth: matchDepth
2116
+ });
2117
+ continue;
2118
+ }
2119
+ const path = result.text.startsWith('./') ? result.text.slice(2) : result.text;
2120
+ const parts = path.split('/');
2121
+ let directory = '';
2122
+ for (let i = 0; i < parts.length - 1; i++) {
2123
+ directory = directory ? `${directory}/${parts[i]}` : parts[i];
2124
+ if (!directories.has(directory)) {
2125
+ directories.add(directory);
2126
+ listItems.push({
2127
+ depth: i,
2128
+ end: 0,
2129
+ isDirectory: true,
2130
+ lineNumber: 0,
2131
+ start: 0,
2132
+ text: directory,
2133
+ type: File
2134
+ });
2135
+ }
2136
+ }
2137
+ matchDepth = parts.length;
2138
+ listItems.push({
2139
+ ...result,
2140
+ depth: matchDepth - 1,
2141
+ text: path
2142
+ });
2143
+ }
2144
+ return listItems;
2145
+ };
2146
+
2147
+ const getScrollBarSize$1 = (size, contentSize, minimumSliderSize) => {
2148
+ if (size >= contentSize) {
2149
+ return 0;
2150
+ }
2151
+ return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
2152
+ };
2153
+ const getScrollBarOffset$1 = (delta, finalDelta, size, scrollBarSize) => {
2154
+ const scrollBarOffset = delta / finalDelta * (size - scrollBarSize);
2155
+ return scrollBarOffset;
2156
+ };
2157
+ const getScrollBarY$1 = getScrollBarOffset$1;
2158
+
2115
2159
  const getFilePath = text => {
2116
2160
  // TODO make api stricter so that results always have the same shape
2117
2161
  if (text.startsWith('./')) {
@@ -2120,13 +2164,9 @@ const getFilePath = text => {
2120
2164
  return text;
2121
2165
  };
2122
2166
 
2123
- const File = 1;
2124
- const Match = 2;
2125
- const Context = 3;
2126
-
2127
2167
  const getIconsCached = (dirents, fileIconCache) => {
2128
2168
  return dirents.map(dirent => {
2129
- if (dirent.type !== File) {
2169
+ if (dirent.type !== File || dirent.isDirectory) {
2130
2170
  return '';
2131
2171
  }
2132
2172
  const path = getFilePath(dirent.text);
@@ -2143,7 +2183,7 @@ const getFileName = path => {
2143
2183
  };
2144
2184
 
2145
2185
  const isFile = match => {
2146
- return match.type === File;
2186
+ return match.type === File && !match.isDirectory;
2147
2187
  };
2148
2188
 
2149
2189
  const getMissingDirents = (searchResults, fileIconCache) => {
@@ -2224,60 +2264,72 @@ const getFileIcons = async (items, fileIconCache) => {
2224
2264
  };
2225
2265
  };
2226
2266
 
2227
- const getFilteredResults = (results, collapsedPaths) => {
2228
- if (collapsedPaths.length === 0) {
2229
- return results;
2230
- }
2231
- const filteredResults = [];
2232
- let isExcluded = false;
2233
- for (const result of results) {
2234
- if (result.type === File) {
2235
- filteredResults.push(result);
2236
- isExcluded = collapsedPaths.includes(result.text) ? true : false;
2237
- }
2238
- if ((result.type === Match || result.type === Context) && !isExcluded) {
2239
- filteredResults.push(result);
2240
- }
2267
+ const updateVisibleFileIcons = async (state, fileIconCache) => {
2268
+ const {
2269
+ fileIconCache: currentFileIconCache,
2270
+ listItems,
2271
+ maxLineY,
2272
+ minLineY
2273
+ } = state;
2274
+ const visibleItems = listItems.slice(minLineY, maxLineY);
2275
+ const {
2276
+ icons,
2277
+ newFileIconCache
2278
+ } = await getFileIcons(visibleItems, currentFileIconCache);
2279
+ return {
2280
+ ...state,
2281
+ fileIconCache: newFileIconCache,
2282
+ icons
2283
+ };
2284
+ };
2285
+ const updateVisibleFileIconsWhenRangeChanges = async (oldState, newState) => {
2286
+ if (oldState.listItems === newState.listItems && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY) {
2287
+ return newState;
2241
2288
  }
2242
- return filteredResults;
2289
+ return updateVisibleFileIcons(newState);
2243
2290
  };
2244
2291
 
2245
- // TODO optimize this function to return the minimum number
2246
- // of visible items needed, e.g. when not scrolled 5 items with
2247
- // 20px fill 100px but when scrolled 6 items are needed
2248
- const getNumberOfVisibleItems$1 = (listHeight, itemHeight) => {
2249
- return Math.ceil(listHeight / itemHeight) + 1;
2250
- };
2292
+ const List = 1;
2293
+ const Tree = 2;
2251
2294
 
2252
2295
  const applyCollapsedPaths = async (state, collapsedPaths, listFocusedIndex) => {
2253
2296
  const {
2254
- fileIconCache,
2297
+ deltaY: oldDeltaY,
2255
2298
  headerHeight,
2256
2299
  height,
2257
2300
  itemHeight,
2258
- items
2301
+ items,
2302
+ minimumSliderSize,
2303
+ viewMode
2259
2304
  } = state;
2260
- const filteredResults = getFilteredResults(items, collapsedPaths);
2261
- const {
2262
- icons,
2263
- newFileIconCache
2264
- } = await getFileIcons(filteredResults, fileIconCache);
2305
+ const sourceItems = viewMode === Tree ? getTreeListItems(items) : items;
2306
+ const filteredResults = getFilteredResults(sourceItems, collapsedPaths);
2265
2307
  const total = filteredResults.length;
2266
2308
  const listHeight = height - headerHeight;
2309
+ const contentHeight = total * itemHeight;
2310
+ const finalDeltaY = Math.max(contentHeight - listHeight, 0);
2311
+ const deltaY = clamp$1(oldDeltaY, 0, finalDeltaY);
2312
+ const minLineY = Math.floor(deltaY / itemHeight);
2267
2313
  const numberOfVisible = getNumberOfVisibleItems$1(listHeight, itemHeight);
2268
- const maxLineY = Math.min(numberOfVisible, total);
2269
- return {
2314
+ const maxLineY = Math.min(minLineY + numberOfVisible, total);
2315
+ const scrollBarHeight = getScrollBarSize$1(height, contentHeight, minimumSliderSize);
2316
+ const scrollBarY = finalDeltaY === 0 ? 0 : getScrollBarY$1(deltaY, finalDeltaY, listHeight, scrollBarHeight);
2317
+ const updatedState = {
2270
2318
  ...state,
2271
2319
  collapsedPaths,
2272
- fileIconCache: newFileIconCache,
2320
+ deltaY,
2321
+ finalDeltaY,
2273
2322
  focus: FocusSearchResults,
2274
2323
  focusSource: Script,
2275
- icons,
2276
2324
  listFocused: true,
2277
2325
  listFocusedIndex,
2278
2326
  listItems: filteredResults,
2279
- maxLineY
2327
+ maxLineY,
2328
+ minLineY,
2329
+ scrollBarHeight,
2330
+ scrollBarY
2280
2331
  };
2332
+ return updateVisibleFileIcons(updatedState);
2281
2333
  };
2282
2334
 
2283
2335
  const getPaths = items => {
@@ -2292,12 +2344,13 @@ const getPaths = items => {
2292
2344
  const collapseAll$1 = async state => {
2293
2345
  const {
2294
2346
  items,
2295
- listFocusedIndex
2347
+ listFocusedIndex,
2348
+ listItems
2296
2349
  } = state;
2297
2350
  if (items.length === 0) {
2298
2351
  return state;
2299
2352
  }
2300
- const paths = getPaths(items);
2353
+ const paths = getPaths(listItems);
2301
2354
  return applyCollapsedPaths(state, paths, listFocusedIndex);
2302
2355
  };
2303
2356
 
@@ -2363,13 +2416,6 @@ const getHeaderHeightForFlags = (headerHeight, oldFlags, newFlags) => {
2363
2416
  return newTopHeight + additionalHeight;
2364
2417
  };
2365
2418
 
2366
- const invoke$1 = (method, ...params) => {
2367
- return get$1(TextMeasurementWorker).invoke(method, ...params);
2368
- };
2369
- const set$2 = rpc => {
2370
- set$9(TextMeasurementWorker, rpc);
2371
- };
2372
-
2373
2419
  const SearchMessageFontFamily = 'system-ui';
2374
2420
  const SearchMessageFontSize = 13;
2375
2421
  const SearchMessageLineHeight = 13;
@@ -2381,7 +2427,7 @@ const getSearchMessageHeight = async (message, width, flags) => {
2381
2427
  }
2382
2428
  const horizontalSpace = hasDetailsExpanded(flags) ? SearchMessageExpandedHorizontalSpace : SearchMessageCollapsedHorizontalSpace;
2383
2429
  const availableWidth = Math.max(width - horizontalSpace, 1);
2384
- const textHeight = await invoke$1('TextMeasurement.measureTextBlockHeight', message, SearchMessageFontFamily, SearchMessageFontSize, SearchMessageLineHeight, availableWidth);
2430
+ const textHeight = await invoke$3('TextMeasurement.measureTextBlockHeight', message, SearchMessageFontFamily, SearchMessageFontSize, SearchMessageLineHeight, availableWidth);
2385
2431
  return Math.max(textHeight + VerticalPadding, Minimum);
2386
2432
  };
2387
2433
 
@@ -2503,11 +2549,10 @@ const {
2503
2549
  set: set$1,
2504
2550
  wrapAsyncCommand,
2505
2551
  wrapCommand,
2506
- wrapGetter
2552
+ wrapGetter,
2553
+ wrapSerialCommand
2507
2554
  } = create$2();
2508
2555
 
2509
- const List = 1;
2510
-
2511
2556
  const create$1 = ({
2512
2557
  headerHeight = 0,
2513
2558
  itemHeight,
@@ -2824,18 +2869,6 @@ const removeItemFromItems = (items, index, matchCount, fileCount) => {
2824
2869
  };
2825
2870
  };
2826
2871
 
2827
- const getScrollBarSize$1 = (size, contentSize, minimumSliderSize) => {
2828
- if (size >= contentSize) {
2829
- return 0;
2830
- }
2831
- return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
2832
- };
2833
- const getScrollBarOffset$1 = (delta, finalDelta, size, scrollBarSize) => {
2834
- const scrollBarOffset = delta / finalDelta * (size - scrollBarSize);
2835
- return scrollBarOffset;
2836
- };
2837
- const getScrollBarY$1 = getScrollBarOffset$1;
2838
-
2839
2872
  const emptyObject = {};
2840
2873
  const i18nString = (key, placeholders = emptyObject) => {
2841
2874
  if (placeholders === emptyObject) {
@@ -3125,7 +3158,6 @@ const removeIndex = async (state, index) => {
3125
3158
  const {
3126
3159
  deltaY,
3127
3160
  fileCount,
3128
- fileIconCache,
3129
3161
  height,
3130
3162
  itemHeight,
3131
3163
  items,
@@ -3158,19 +3190,12 @@ const removeIndex = async (state, index) => {
3158
3190
  const listHeight = height - headerHeight;
3159
3191
  const scrollBarHeight = getScrollBarSize$1(height, contentHeight, minimumSliderSize);
3160
3192
  const finalDeltaY = Math.max(contentHeight - listHeight, 0);
3161
- const visible = newItems.slice(0, maxLineY);
3162
- const {
3163
- icons,
3164
- newFileIconCache
3165
- } = await getFileIcons(visible, fileIconCache);
3166
- return {
3193
+ const updatedState = {
3167
3194
  ...state,
3168
3195
  deltaY: newDeltaY,
3169
3196
  fileCount: newFileCount,
3170
- fileIconCache: newFileIconCache,
3171
3197
  finalDeltaY,
3172
3198
  headerHeight,
3173
- icons,
3174
3199
  items: newItems,
3175
3200
  listFocusedIndex: newFocusedIndex,
3176
3201
  listItems: newItems,
@@ -3181,6 +3206,7 @@ const removeIndex = async (state, index) => {
3181
3206
  minLineY: newMinLineY,
3182
3207
  scrollBarHeight
3183
3208
  };
3209
+ return updateVisibleFileIcons(updatedState);
3184
3210
  };
3185
3211
 
3186
3212
  const dismissItem = state => {
@@ -3380,6 +3406,10 @@ const focusSearchValueNext = state => {
3380
3406
  return focusMatchCase$1(state);
3381
3407
  };
3382
3408
 
3409
+ const getComponentState = uid => {
3410
+ return get(uid).newState;
3411
+ };
3412
+
3383
3413
  const Tab = 2;
3384
3414
  const Enter = 3;
3385
3415
  const End = 255;
@@ -3585,7 +3615,7 @@ const getMenuEntriesFile = (state, props) => {
3585
3615
  label: copyAll()
3586
3616
  }, menuEntrySeparator, {
3587
3617
  args: [uri],
3588
- command: 'Search.revealInExplorer',
3618
+ command: 'RevealInExplorer.reveal',
3589
3619
  flags: None$1,
3590
3620
  id: 'revealInExplorerView',
3591
3621
  label: revealInExplorerView()
@@ -3611,7 +3641,7 @@ const getMenuEntriesMatch = (state, props) => {
3611
3641
  label: copyAll()
3612
3642
  }, menuEntrySeparator, {
3613
3643
  args: [uri],
3614
- command: 'Search.revealInExplorer',
3644
+ command: 'RevealInExplorer.reveal',
3615
3645
  flags: None$1,
3616
3646
  id: 'revealInExplorerView',
3617
3647
  label: revealInExplorerView()
@@ -3690,7 +3720,7 @@ const openSearchEditor = async state => {
3690
3720
 
3691
3721
  const getSearchExcludes = async (fallback = []) => {
3692
3722
  try {
3693
- const value = await invoke$3('Preferences.get', 'search.exclude');
3723
+ const value = await invoke$2('Preferences.get', 'search.exclude');
3694
3724
  if (Array.isArray(value)) {
3695
3725
  return value.filter(item => typeof item === 'string');
3696
3726
  }
@@ -3781,7 +3811,7 @@ const getSearchHeaderHeight = (flags, messageHeight, warningHeight) => {
3781
3811
  };
3782
3812
 
3783
3813
  const measureTextHeight = (text, fontFamily, fontSize, lineHeight, width) => {
3784
- return invoke$3('MeasureTextHeight.measureTextBlockHeight', text, fontFamily, fontSize, `${lineHeight}px`, width);
3814
+ return invoke$2('MeasureTextHeight.measureTextBlockHeight', text, fontFamily, fontSize, `${lineHeight}px`, width);
3785
3815
  };
3786
3816
 
3787
3817
  const SearchWarningFontFamily = 'system-ui';
@@ -3821,7 +3851,7 @@ const textSearch = async (root, query, options, assetDir, platform, searchId, ui
3821
3851
  if (!hasOpenEditors(options.flags)) {
3822
3852
  return search$1(root, query, options, assetDir, platform, searchId, uid);
3823
3853
  }
3824
- const openEditorUris = await invoke$3('GetActiveEditor.getOpenEditorUris');
3854
+ const openEditorUris = await invoke$2('GetActiveEditor.getOpenEditorUris');
3825
3855
  return search$1(root, query, {
3826
3856
  ...options,
3827
3857
  openEditorUris
@@ -3859,7 +3889,13 @@ const handleUpdateFull = async (state, update) => {
3859
3889
  const scheme = getProtocol(root);
3860
3890
  const isFileSearch = scheme === '' || scheme === 'file';
3861
3891
  const shouldUsePullBasedSearch = usePullBasedSearch && isFileSearch;
3862
- const searchId = shouldUsePullBasedSearch ? crypto.randomUUID() : '';
3892
+ const searchId = crypto.randomUUID();
3893
+ const current = get(uid);
3894
+ const oldState = current ? current.oldState : state;
3895
+ set$1(uid, oldState, {
3896
+ ...partialNewState,
3897
+ searchId
3898
+ });
3863
3899
  const {
3864
3900
  limitHit,
3865
3901
  results
@@ -3881,6 +3917,10 @@ const handleUpdateFull = async (state, update) => {
3881
3917
  usePullBasedSearch: shouldUsePullBasedSearch,
3882
3918
  useRegularExpression: Boolean(flags & UseRegularExpression$2)
3883
3919
  }, assetDir, platform, searchId, uid);
3920
+ const latestAfterSearch = get(uid);
3921
+ if (latestAfterSearch.newState.searchId !== searchId) {
3922
+ return state;
3923
+ }
3884
3924
  if (!Array.isArray(results)) {
3885
3925
  throw new TypeError('results must be of type array');
3886
3926
  }
@@ -3904,8 +3944,12 @@ const handleUpdateFull = async (state, update) => {
3904
3944
  icons,
3905
3945
  newFileIconCache
3906
3946
  } = await getFileIcons(visible, fileIconCache);
3907
- return {
3908
- ...partialNewState,
3947
+ const latest = get(uid);
3948
+ if (latest.newState.searchId !== searchId) {
3949
+ return state;
3950
+ }
3951
+ const updatedState = {
3952
+ ...latest.newState,
3909
3953
  collapsedPaths: [],
3910
3954
  deltaY: 0,
3911
3955
  fileCount,
@@ -3929,6 +3973,8 @@ const handleUpdateFull = async (state, update) => {
3929
3973
  threads,
3930
3974
  value
3931
3975
  };
3976
+ set$1(uid, latest.oldState, updatedState);
3977
+ return state;
3932
3978
  };
3933
3979
 
3934
3980
  const waitForNextFrame = async () => {
@@ -3968,8 +4014,7 @@ const textSearchIncremental = async (root, query, options, assetDir, platform, s
3968
4014
  minLineY: 0
3969
4015
  };
3970
4016
  set$1(uid, latest2.oldState, updatedState2);
3971
- // @ts-ignore
3972
- await invoke$3('Search.rerender');
4017
+ await invoke$2('Viewlet.requestRender', uid);
3973
4018
  await waitForNextFrame();
3974
4019
  }
3975
4020
  await resultPromise;
@@ -4092,6 +4137,9 @@ const handleUpdatePullBased = async (state, update) => {
4092
4137
  if (!latest) {
4093
4138
  return state;
4094
4139
  }
4140
+ if (latest.newState.searchId !== searchId) {
4141
+ return state;
4142
+ }
4095
4143
  const limitHitWarning = limitHit ? theResultSetOnlyContainsASubSetOfMatches() : '';
4096
4144
  const {
4097
4145
  fileCount,
@@ -4099,15 +4147,21 @@ const handleUpdatePullBased = async (state, update) => {
4099
4147
  } = getTextSearchResultCounts(latest.newState.items);
4100
4148
  const message = getStatusMessage(resultCount, fileCount);
4101
4149
  const [messageHeight, warningHeight] = await Promise.all([getSearchMessageHeight(message, width, flags), getSearchWarningMessageHeight(limitHitWarning, width)]);
4150
+ const current = get(uid);
4151
+ if (current.newState.searchId !== searchId) {
4152
+ return state;
4153
+ }
4102
4154
  const headerHeight = getSearchHeaderHeight(flags, messageHeight, warningHeight);
4103
- return {
4104
- ...latest.newState,
4155
+ const updatedState = {
4156
+ ...current.newState,
4105
4157
  headerHeight,
4106
4158
  limitHit,
4107
4159
  limitHitWarning,
4108
4160
  message,
4109
4161
  messageHeight
4110
4162
  };
4163
+ set$1(uid, current.oldState, updatedState);
4164
+ return state;
4111
4165
  };
4112
4166
 
4113
4167
  const handleUpdateValidationError = (state, update, searchInputErrorMessage) => {
@@ -4163,7 +4217,12 @@ const handleUpdate = async (state, update) => {
4163
4217
  workspacePath
4164
4218
  } = partialNewState;
4165
4219
  if (isEmptyString(value) || isEmptyString(workspacePath)) {
4166
- return handleUpdateEmpty(state, update);
4220
+ const newState = handleUpdateEmpty(state, update);
4221
+ const current = get(newState.uid);
4222
+ if (current) {
4223
+ set$1(newState.uid, current.oldState, newState);
4224
+ }
4225
+ return newState;
4167
4226
  }
4168
4227
  const searchInputErrorMessage = validateSearchInput(value, flags);
4169
4228
  if (searchInputErrorMessage) {
@@ -4193,7 +4252,36 @@ const refresh = async state => {
4193
4252
  };
4194
4253
 
4195
4254
  const viewAsTree = async state => {
4196
- return state;
4255
+ const {
4256
+ headerHeight,
4257
+ height,
4258
+ itemHeight,
4259
+ items,
4260
+ minimumSliderSize
4261
+ } = state;
4262
+ if (items.length === 0) {
4263
+ return state;
4264
+ }
4265
+ const listItems = getTreeListItems(items);
4266
+ const total = listItems.length;
4267
+ const contentHeight = total * itemHeight;
4268
+ const listHeight = height - headerHeight;
4269
+ const finalDeltaY = Math.max(contentHeight - listHeight, 0);
4270
+ const numberOfVisible = getNumberOfVisibleItems$1(listHeight, itemHeight);
4271
+ const maxLineY = Math.min(numberOfVisible, total);
4272
+ const scrollBarHeight = getScrollBarSize$1(height, contentHeight, minimumSliderSize);
4273
+ const updatedState = {
4274
+ ...state,
4275
+ collapsedPaths: [],
4276
+ deltaY: 0,
4277
+ finalDeltaY,
4278
+ listItems,
4279
+ maxLineY,
4280
+ minLineY: 0,
4281
+ scrollBarHeight,
4282
+ viewMode: Tree
4283
+ };
4284
+ return updateVisibleFileIcons(updatedState);
4197
4285
  };
4198
4286
 
4199
4287
  const handleActionClick = async (state, name) => {
@@ -4225,7 +4313,7 @@ const noop = state => {
4225
4313
  };
4226
4314
 
4227
4315
  const applyBulkReplacement = async bulkEdits => {
4228
- await invoke$3('BulkReplacement.applyBulkReplacement', bulkEdits);
4316
+ await invoke$2('BulkReplacement.applyBulkReplacement', bulkEdits);
4229
4317
  };
4230
4318
 
4231
4319
  const getReplacedMessage = (fileCount, replaceCount, replacement) => {
@@ -4292,17 +4380,9 @@ const getReplacingMessage = (fileCount, replaceCount) => {
4292
4380
  return replacingManyOccurrencesInManyFiles(replaceCount, fileCount);
4293
4381
  };
4294
4382
 
4295
- const missingDialogWorkerRelay = 'Command "SendMessagePortToExtensionHostWorker.sendMessagePortToDialogWorker" not found';
4296
- const prompt = async (text, options) => {
4297
- try {
4298
- return await invoke$6('ConfirmPrompt.prompt', text, options);
4299
- } catch (error) {
4300
- if (!String(error).includes(missingDialogWorkerRelay)) {
4301
- throw error;
4302
- }
4303
- return invoke$3('ConfirmPrompt.prompt', text, options);
4304
- }
4305
- };
4383
+ const {
4384
+ prompt
4385
+ } = DialogWorker;
4306
4386
 
4307
4387
  const getReplaceAllConfirmText = (matchCount, fileCount, replacement) => {
4308
4388
  if (matchCount === 1) {
@@ -4375,7 +4455,6 @@ const replaceAllInFocusedFile = async (state, fileIndex) => {
4375
4455
  const {
4376
4456
  deltaY,
4377
4457
  fileCount,
4378
- fileIconCache,
4379
4458
  height,
4380
4459
  itemHeight,
4381
4460
  items,
@@ -4415,19 +4494,12 @@ const replaceAllInFocusedFile = async (state, fileIndex) => {
4415
4494
  const listHeight = height - headerHeight;
4416
4495
  const scrollBarHeight = getScrollBarSize$1(height, contentHeight, minimumSliderSize);
4417
4496
  const finalDeltaY = Math.max(contentHeight - listHeight, 0);
4418
- const visible = newItems.slice(0, newMaxLineY);
4419
- const {
4420
- icons,
4421
- newFileIconCache
4422
- } = await getFileIcons(visible, fileIconCache);
4423
- return {
4497
+ const updatedState = {
4424
4498
  ...state,
4425
4499
  deltaY: newDeltaY,
4426
4500
  fileCount: newFileCount,
4427
- fileIconCache: newFileIconCache,
4428
4501
  finalDeltaY,
4429
4502
  headerHeight,
4430
- icons,
4431
4503
  items: newItems,
4432
4504
  listFocusedIndex: newFocusedIndex,
4433
4505
  listItems: newItems,
@@ -4436,8 +4508,10 @@ const replaceAllInFocusedFile = async (state, fileIndex) => {
4436
4508
  message,
4437
4509
  messageHeight,
4438
4510
  minLineY: newMinLineY,
4439
- scrollBarHeight
4511
+ scrollBarHeight,
4512
+ searchId: ''
4440
4513
  };
4514
+ return updateVisibleFileIcons(updatedState);
4441
4515
  };
4442
4516
  const confirmReplaceAll = async (state, fileIndex) => {
4443
4517
  const {
@@ -4465,9 +4539,11 @@ const replaceAllConfirmed = async (state, fileIndex) => {
4465
4539
  workspacePath
4466
4540
  } = state;
4467
4541
  const bulkEdits = getReplaceElements(items, workspacePath, replacement);
4468
- // TODO this function should return an error message if an error occurred during bulk edit
4469
- await applyBulkReplacement(bulkEdits);
4470
- await handleWorkspaceRefresh();
4542
+ if (bulkEdits.length > 0) {
4543
+ // TODO this function should return an error message if an error occurred during bulk edit
4544
+ await applyBulkReplacement(bulkEdits);
4545
+ await handleWorkspaceRefresh();
4546
+ }
4471
4547
  const fileCount = bulkEdits.length;
4472
4548
  const message = getReplacedMessage(fileCount, matchCount, replacement);
4473
4549
  const {
@@ -4482,7 +4558,8 @@ const replaceAllConfirmed = async (state, fileIndex) => {
4482
4558
  maxLineY: 0,
4483
4559
  message,
4484
4560
  messageHeight,
4485
- minLineY: 0
4561
+ minLineY: 0,
4562
+ searchId: ''
4486
4563
  };
4487
4564
  };
4488
4565
  const replaceAll = async state => {
@@ -4498,7 +4575,9 @@ const replaceAllWithProgress = async context => {
4498
4575
  const state = context.getState();
4499
4576
  const {
4500
4577
  fileCount: totalFileCount,
4501
- matchCount: totalMatchCount
4578
+ matchCount: totalMatchCount,
4579
+ searchId: activeSearchId,
4580
+ uid
4502
4581
  } = state;
4503
4582
  const actualIndex = getActualIndex(state);
4504
4583
  const fileIndex = getFileIndex(state, actualIndex);
@@ -4508,16 +4587,49 @@ const replaceAllWithProgress = async context => {
4508
4587
  if (!shouldReplace) {
4509
4588
  return;
4510
4589
  }
4511
- const message = getReplacingMessage(fileCount, matchCount);
4512
- const messageLayout = await getSearchMessageLayout(state, message);
4590
+ if (context.getState().searchId !== activeSearchId) {
4591
+ return;
4592
+ }
4593
+ const replacementSearchId = crypto.randomUUID();
4594
+ let progressUpdate = {};
4595
+ if (matchCount > 0) {
4596
+ const message = getReplacingMessage(fileCount, matchCount);
4597
+ const messageLayout = await getSearchMessageLayout(state, message);
4598
+ progressUpdate = {
4599
+ ...messageLayout,
4600
+ message
4601
+ };
4602
+ }
4513
4603
  await context.updateState(latestState => ({
4514
4604
  ...latestState,
4515
- ...messageLayout,
4516
- message
4605
+ ...progressUpdate,
4606
+ searchId: replacementSearchId
4517
4607
  }));
4518
- await invoke$3('Search.rerender');
4519
- const updatedState = await replaceAllConfirmed(context.getState(), fileIndex);
4520
- await context.updateState(() => updatedState);
4608
+ if (matchCount > 0) {
4609
+ await invoke$2('Viewlet.requestRender', uid);
4610
+ }
4611
+ const currentBeforeReplacement = get(uid);
4612
+ let replacementState = context.getState();
4613
+ if (currentBeforeReplacement && currentBeforeReplacement.newState.searchId !== replacementSearchId) {
4614
+ if (currentBeforeReplacement.newState.searchId !== activeSearchId) {
4615
+ return;
4616
+ }
4617
+ replacementState = {
4618
+ ...currentBeforeReplacement.newState,
4619
+ ...progressUpdate,
4620
+ searchId: replacementSearchId
4621
+ };
4622
+ }
4623
+ const generationState = {
4624
+ ...replacementState
4625
+ };
4626
+ set$1(uid, generationState, generationState);
4627
+ const updatedState = await replaceAllConfirmed(generationState, fileIndex);
4628
+ const completedGenerationState = {
4629
+ ...updatedState
4630
+ };
4631
+ set$1(uid, completedGenerationState, completedGenerationState);
4632
+ set$1(uid, generationState, updatedState);
4521
4633
  };
4522
4634
 
4523
4635
  const toggleContextLines = async state => {
@@ -4669,21 +4781,11 @@ const handleHeaderFocusOut = state => {
4669
4781
  };
4670
4782
 
4671
4783
  const handleIconThemeChange = async state => {
4672
- const {
4673
- items,
4674
- maxLineY,
4675
- minLineY
4676
- } = state;
4677
- const visibleItems = items.slice(minLineY, maxLineY);
4678
- const {
4679
- icons,
4680
- newFileIconCache
4681
- } = await getFileIcons(visibleItems, {});
4682
- return {
4784
+ const stateWithEmptyIconCache = {
4683
4785
  ...state,
4684
- fileIconCache: newFileIconCache,
4685
- icons
4786
+ fileIconCache: {}
4686
4787
  };
4788
+ return updateVisibleFileIcons(stateWithEmptyIconCache);
4687
4789
  };
4688
4790
 
4689
4791
  const handleIncludeInput = (state, includeValue, inputSource = Script) => {
@@ -4808,6 +4910,7 @@ const getNewSelections = (selections, name, newValue) => {
4808
4910
  }
4809
4911
  };
4810
4912
  };
4913
+
4811
4914
  const updateValue = (state, name, newValue) => {
4812
4915
  const {
4813
4916
  selections
@@ -5038,7 +5141,7 @@ const handleMessagePort = async (port, viewletCommandMap, setAsRendererProcess =
5038
5141
  throw new TypeError(`Viewlet command not found: ${command}`);
5039
5142
  }
5040
5143
  await fn(uid, ...args);
5041
- await invoke$3('Viewlet.requestRender', uid);
5144
+ await invoke$2('Viewlet.requestRender', uid);
5042
5145
  };
5043
5146
  const rpc = await create$7({
5044
5147
  commandMap: {
@@ -5052,7 +5155,7 @@ const handleMessagePort = async (port, viewletCommandMap, setAsRendererProcess =
5052
5155
  };
5053
5156
 
5054
5157
  const openFolder = async () => {
5055
- await invoke$3('Dialog.openFolder');
5158
+ await invoke$2('Dialog.openFolder');
5056
5159
  };
5057
5160
 
5058
5161
  const handleOpenFolderClick = async state => {
@@ -5062,17 +5165,19 @@ const handleOpenFolderClick = async state => {
5062
5165
 
5063
5166
  const handlePullResultsFound = async (state, resultSearchId, newResults) => {
5064
5167
  const {
5065
- fileIconCache,
5066
- height,
5067
- itemHeight,
5068
- listItems,
5069
- minimumSliderSize,
5070
- searchId,
5071
5168
  uid
5072
5169
  } = state;
5073
- if (searchId !== resultSearchId) {
5170
+ const current = get(uid);
5171
+ if (!current || current.newState.searchId !== resultSearchId) {
5074
5172
  return state;
5075
5173
  }
5174
+ const {
5175
+ fileIconCache,
5176
+ height,
5177
+ itemHeight,
5178
+ listItems,
5179
+ minimumSliderSize
5180
+ } = current.newState;
5076
5181
  const allResults = [...listItems, ...newResults];
5077
5182
  const {
5078
5183
  fileCount,
@@ -5082,7 +5187,7 @@ const handlePullResultsFound = async (state, resultSearchId, newResults) => {
5082
5187
  const {
5083
5188
  headerHeight,
5084
5189
  messageHeight
5085
- } = await getSearchMessageLayout(state, message);
5190
+ } = await getSearchMessageLayout(current.newState, message);
5086
5191
  const total = allResults.length;
5087
5192
  const contentHeight = total * itemHeight;
5088
5193
  const listHeight = height - headerHeight;
@@ -5096,6 +5201,9 @@ const handlePullResultsFound = async (state, resultSearchId, newResults) => {
5096
5201
  newFileIconCache
5097
5202
  } = await getFileIcons(visible, fileIconCache);
5098
5203
  const latest = get(uid);
5204
+ if (!latest || latest.newState.searchId !== resultSearchId) {
5205
+ return state;
5206
+ }
5099
5207
  const updatedState = {
5100
5208
  ...latest.newState,
5101
5209
  fileCount,
@@ -5113,16 +5221,11 @@ const handlePullResultsFound = async (state, resultSearchId, newResults) => {
5113
5221
  minLineY: 0,
5114
5222
  scrollBarHeight
5115
5223
  };
5116
- const oldState = latest ? latest.oldState : state;
5117
- set$1(uid, oldState, updatedState);
5118
- await invoke$3('Search.rerender');
5224
+ set$1(uid, latest.oldState, updatedState);
5225
+ await invoke$2('Viewlet.requestRender', uid);
5119
5226
  return state;
5120
5227
  };
5121
5228
 
5122
- const clamp$1 = (num, min, max) => {
5123
- return Math.min(Math.max(num, min), max);
5124
- };
5125
-
5126
5229
  const handleResize = async (state, x, y, width, height) => {
5127
5230
  const {
5128
5231
  deltaY,
@@ -5278,7 +5381,7 @@ const focusIndexScrollUp = (state, index, listHeight, itemHeight, itemsLength) =
5278
5381
  scrollBarY
5279
5382
  };
5280
5383
  };
5281
- const focusIndex = (state, index) => {
5384
+ const focusIndex$1 = (state, index) => {
5282
5385
  const {
5283
5386
  headerHeight,
5284
5387
  height,
@@ -5326,24 +5429,24 @@ const next = (items, index) => {
5326
5429
  const previous = (items, index) => {
5327
5430
  return (index === 0 ? items.length : index) - 1;
5328
5431
  };
5329
- const focusFirst = state => {
5432
+ const focusFirst$1 = state => {
5330
5433
  const firstIndex = first();
5331
- return focusIndex(state, firstIndex);
5434
+ return focusIndex$1(state, firstIndex);
5332
5435
  };
5333
- const focusLast = state => {
5436
+ const focusLast$1 = state => {
5334
5437
  const {
5335
5438
  items
5336
5439
  } = state;
5337
5440
  const lastIndex = last(items);
5338
- return focusIndex(state, lastIndex);
5441
+ return focusIndex$1(state, lastIndex);
5339
5442
  };
5340
- const focusNext = state => {
5443
+ const focusNext$1 = state => {
5341
5444
  const {
5342
5445
  focusedIndex,
5343
5446
  items
5344
5447
  } = state;
5345
5448
  const nextIndex = next(items, focusedIndex);
5346
- return focusIndex(state, nextIndex);
5449
+ return focusIndex$1(state, nextIndex);
5347
5450
  };
5348
5451
 
5349
5452
  // based on https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/common/arrays.ts#L625 (License MIT)
@@ -5354,7 +5457,7 @@ const isLastIndex = (array, index) => {
5354
5457
  const lastIndex = array => {
5355
5458
  return array.length - 1;
5356
5459
  };
5357
- const focusNextPage = state => {
5460
+ const focusNextPage$1 = state => {
5358
5461
  const {
5359
5462
  focusedIndex,
5360
5463
  items,
@@ -5365,9 +5468,9 @@ const focusNextPage = state => {
5365
5468
  return state;
5366
5469
  }
5367
5470
  const indexNextPage = Math.min(maxLineY + (maxLineY - minLineY) - 2, lastIndex(items));
5368
- return focusIndex(state, indexNextPage);
5471
+ return focusIndex$1(state, indexNextPage);
5369
5472
  };
5370
- const focusPrevious = state => {
5473
+ const focusPrevious$1 = state => {
5371
5474
  const {
5372
5475
  focusedIndex,
5373
5476
  items
@@ -5376,9 +5479,9 @@ const focusPrevious = state => {
5376
5479
  return state;
5377
5480
  }
5378
5481
  const previousIndex = previous(items, focusedIndex);
5379
- return focusIndex(state, previousIndex);
5482
+ return focusIndex$1(state, previousIndex);
5380
5483
  };
5381
- const focusPreviousPage = state => {
5484
+ const focusPreviousPage$1 = state => {
5382
5485
  const {
5383
5486
  focusedIndex,
5384
5487
  maxLineY,
@@ -5388,7 +5491,7 @@ const focusPreviousPage = state => {
5388
5491
  return state;
5389
5492
  }
5390
5493
  const indexPreviousPage = Math.max(minLineY - (maxLineY - minLineY) + 1, 0);
5391
- return focusIndex(state, indexPreviousPage);
5494
+ return focusIndex$1(state, indexPreviousPage);
5392
5495
  };
5393
5496
  const handleScrollBarCaptureLost = state => {
5394
5497
  return {
@@ -5439,7 +5542,7 @@ const setDeltaY = (state, value) => {
5439
5542
  scrollBarY
5440
5543
  };
5441
5544
  };
5442
- const handleScrollBarClick = (state, eventY) => {
5545
+ const handleScrollBarClick$1 = (state, eventY) => {
5443
5546
  const {
5444
5547
  deltaY,
5445
5548
  finalDeltaY,
@@ -5478,7 +5581,7 @@ const getNewPercent = (contentHeight, scrollBarHeight, relativeY) => {
5478
5581
  // clicked at bottom
5479
5582
  return 1;
5480
5583
  };
5481
- const handleScrollBarMove = (state, eventY) => {
5584
+ const handleScrollBarMove$1 = (state, eventY) => {
5482
5585
  const {
5483
5586
  finalDeltaY,
5484
5587
  handleOffset,
@@ -5499,6 +5602,54 @@ const handleWheel$1 = (state, deltaMode, deltaY) => {
5499
5602
  return setDeltaY(state, state.deltaY + deltaY);
5500
5603
  };
5501
5604
 
5605
+ const applyListOperation = async (state, operation) => {
5606
+ const {
5607
+ items,
5608
+ listItems
5609
+ } = state;
5610
+ const listState = {
5611
+ ...state,
5612
+ items: listItems
5613
+ };
5614
+ const updatedListState = operation(listState);
5615
+ if (updatedListState === listState) {
5616
+ return state;
5617
+ }
5618
+ const updatedState = {
5619
+ ...updatedListState,
5620
+ items
5621
+ };
5622
+ return updateVisibleFileIconsWhenRangeChanges(state, updatedState);
5623
+ };
5624
+
5625
+ const focusFirst = async state => {
5626
+ return applyListOperation(state, focusFirst$1);
5627
+ };
5628
+
5629
+ const focusIndex = async (state, index) => {
5630
+ return applyListOperation(state, listState => focusIndex$1(listState, index));
5631
+ };
5632
+
5633
+ const focusLast = async state => {
5634
+ return applyListOperation(state, focusLast$1);
5635
+ };
5636
+
5637
+ const focusNext = async state => {
5638
+ return applyListOperation(state, focusNext$1);
5639
+ };
5640
+
5641
+ const focusNextPage = async state => {
5642
+ return applyListOperation(state, focusNextPage$1);
5643
+ };
5644
+
5645
+ const focusPrevious = async state => {
5646
+ return applyListOperation(state, focusPrevious$1);
5647
+ };
5648
+
5649
+ const focusPreviousPage = async state => {
5650
+ return applyListOperation(state, focusPreviousPage$1);
5651
+ };
5652
+
5502
5653
  const getListIndex = (eventX, eventY, x, y, deltaY, itemHeight, topHeight, itemCount) => {
5503
5654
  const relativeY = eventY - y - topHeight + deltaY;
5504
5655
  const index = Math.floor(relativeY / itemHeight);
@@ -5545,8 +5696,10 @@ const selectIndexPreview = async (state, searchResult, index) => {
5545
5696
  const fileResult = listItems[fileIndex];
5546
5697
  const relativePath = getRelativePath(fileResult.text);
5547
5698
  const absolutePath = `${workspacePath}${relativePath}`;
5548
- await openUri(absolutePath, true, {
5549
- selections: new Uint32Array([rowIndex, startColumnIndex, rowIndex, endColumnIndex])
5699
+ await openUri2({
5700
+ focus: true,
5701
+ selections: new Uint32Array([rowIndex, startColumnIndex, rowIndex, endColumnIndex]),
5702
+ uri: absolutePath
5550
5703
  });
5551
5704
  return {
5552
5705
  ...state,
@@ -5616,31 +5769,16 @@ const handleListPointerDown = async (state, button, name) => {
5616
5769
  };
5617
5770
  };
5618
5771
 
5772
+ const handleScrollBarClick = async (state, eventY) => {
5773
+ return applyListOperation(state, listState => handleScrollBarClick$1(listState, eventY));
5774
+ };
5775
+
5776
+ const handleScrollBarMove = async (state, eventY) => {
5777
+ return applyListOperation(state, listState => handleScrollBarMove$1(listState, eventY));
5778
+ };
5779
+
5619
5780
  const handleWheel = async (state, deltaMode, deltaY) => {
5620
- const {
5621
- maxLineY: oldMaxLineY,
5622
- minLineY: oldMinLineY
5623
- } = state;
5624
- const newState = handleWheel$1(state, deltaMode, deltaY);
5625
- if (newState.minLineY === oldMinLineY && newState.maxLineY === oldMaxLineY) {
5626
- return newState;
5627
- }
5628
- const {
5629
- fileIconCache,
5630
- listItems,
5631
- maxLineY,
5632
- minLineY
5633
- } = newState;
5634
- const visibleItems = listItems.slice(minLineY, maxLineY);
5635
- const {
5636
- icons,
5637
- newFileIconCache
5638
- } = await getFileIcons(visibleItems, fileIconCache);
5639
- return {
5640
- ...newState,
5641
- fileIconCache: newFileIconCache,
5642
- icons
5643
- };
5781
+ return applyListOperation(state, listState => handleWheel$1(listState, deltaMode, deltaY));
5644
5782
  };
5645
5783
 
5646
5784
  const getUsePullBasedSearch = async () => {
@@ -5876,24 +6014,32 @@ const getTreeItemIndent = depth => {
5876
6014
  return baseIndent + depth * defaultIndent;
5877
6015
  };
5878
6016
 
5879
- const getSearchDisplayResultFile = (results, fileIcons, i, setSize, collapsedPaths, text, posInSet, relativeIndex, focused, renderFolderPaths, originalResults) => {
6017
+ const normalizeRelativePath = path => {
6018
+ if (path.startsWith('./')) {
6019
+ return path.slice(2);
6020
+ }
6021
+ return path;
6022
+ };
6023
+
6024
+ const getSearchDisplayResultFile = (results, fileIcons, i, setSize, collapsedPaths, text, posInSet, relativeIndex, focused, renderFolderPaths, originalResults, resultDepth, isDirectory) => {
5880
6025
  const path = text;
5881
6026
  const absolutePath = getRelativePath(path);
5882
6027
  const baseName = pathBaseName(path);
5883
6028
  const relativeFolderPath = getRelativeFolderPath(path);
5884
- const displayText = renderFolderPaths && relativeFolderPath ? `${baseName} — ${relativeFolderPath}` : baseName;
5885
- const index = originalResults.indexOf(results[i]);
5886
- const matchCount = getMatchCount(originalResults, index);
6029
+ const displayText = renderFolderPaths && relativeFolderPath && !isDirectory ? `${baseName} — ${relativeFolderPath}` : baseName;
6030
+ const normalizedPath = normalizeRelativePath(path);
6031
+ const index = originalResults.findIndex(result => result.type === results[i].type && normalizeRelativePath(result.text) === normalizedPath);
6032
+ const matchCount = isDirectory ? 0 : getMatchCount(originalResults, index);
5887
6033
  const expanded = collapsedPaths.includes(path) ? Collapsed : Expanded;
5888
- const badgeText = String(matchCount);
5889
- const depth = 0;
6034
+ const badgeText = isDirectory ? '' : String(matchCount);
6035
+ const depth = resultDepth ?? 0;
5890
6036
  const indent = getTreeItemIndent(depth);
5891
6037
  return {
5892
6038
  badgeText,
5893
6039
  depth,
5894
6040
  expanded,
5895
6041
  focused,
5896
- icon: fileIcons[relativeIndex],
6042
+ icon: isDirectory ? '' : fileIcons[relativeIndex],
5897
6043
  indent,
5898
6044
  matchLength: 0,
5899
6045
  matchStart: 0,
@@ -5905,8 +6051,8 @@ const getSearchDisplayResultFile = (results, fileIcons, i, setSize, collapsedPat
5905
6051
  };
5906
6052
  };
5907
6053
 
5908
- const getDisplayResultMatch = (setSize, searchTermLength, replacement, text, posInSet, start, focused) => {
5909
- const depth = 1;
6054
+ const getDisplayResultMatch = (setSize, searchTermLength, replacement, text, posInSet, start, focused, resultDepth = 1) => {
6055
+ const depth = resultDepth;
5910
6056
  const indent = getTreeItemIndent(depth);
5911
6057
  return {
5912
6058
  badgeText: '',
@@ -5928,6 +6074,8 @@ const getDisplayResultMatch = (setSize, searchTermLength, replacement, text, pos
5928
6074
  const getDisplayResult = (results, fileIcons, i, setSize, searchTermLength, replacement, focusedIndex, collapsedPaths, renderFolderPaths, minLineY, originalResults) => {
5929
6075
  const result = results[i];
5930
6076
  const {
6077
+ depth,
6078
+ isDirectory,
5931
6079
  start,
5932
6080
  text,
5933
6081
  type
@@ -5937,11 +6085,11 @@ const getDisplayResult = (results, fileIcons, i, setSize, searchTermLength, repl
5937
6085
  const relativeIndex = i - minLineY;
5938
6086
  switch (type) {
5939
6087
  case Context:
5940
- return getDisplayResultMatch(setSize, 0, '', text, posInSet, 0, focused);
6088
+ return getDisplayResultMatch(setSize, 0, '', text, posInSet, 0, focused, depth);
5941
6089
  case File:
5942
- return getSearchDisplayResultFile(results, fileIcons, i, setSize, collapsedPaths, text, posInSet, relativeIndex, focused, renderFolderPaths, originalResults);
6090
+ return getSearchDisplayResultFile(results, fileIcons, i, setSize, collapsedPaths, text, posInSet, relativeIndex, focused, renderFolderPaths, originalResults, depth, isDirectory);
5943
6091
  case Match:
5944
- return getDisplayResultMatch(setSize, searchTermLength, replacement, text, posInSet, start, focused);
6092
+ return getDisplayResultMatch(setSize, searchTermLength, replacement, text, posInSet, start, focused, depth);
5945
6093
  default:
5946
6094
  throw new Error('unexpected search result type');
5947
6095
  }
@@ -6711,7 +6859,7 @@ const highlighted = {
6711
6859
  };
6712
6860
  const label1 = {
6713
6861
  childCount: 1,
6714
- className: mergeClassNames(Label$1, Grow),
6862
+ className: mergeClassNames(Label, Grow),
6715
6863
  type: Div
6716
6864
  };
6717
6865
  const label3 = {
@@ -6829,10 +6977,10 @@ const getSearchResultsVirtualDom = (visibleItems, focusOutline, scrollbarHeight,
6829
6977
  const childCount = scrollbarHeight === 0 ? 1 : 2;
6830
6978
  return [{
6831
6979
  childCount,
6832
- className: mergeClassNames(Viewlet, List$1, Tree, focusOutline ? FocusOutline : Empty$1),
6980
+ className: mergeClassNames(Viewlet, List$1, Tree$1, focusOutline ? FocusOutline : Empty$1),
6833
6981
  onBlur: HandleListBlur,
6834
6982
  onFocus: HandleListFocus,
6835
- role: Tree$1,
6983
+ role: Tree$2,
6836
6984
  tabIndex: Focusable,
6837
6985
  type: Div
6838
6986
  // TODO renable this when dom diffing is supported
@@ -6840,7 +6988,7 @@ const getSearchResultsVirtualDom = (visibleItems, focusOutline, scrollbarHeight,
6840
6988
  }, ...getTreeItemsVirtualDom(visibleItems, deltaY, itemHeight), ...getScrollBarVirtualDom(scrollbarHeight, scrollBarY, scrollBarValue)];
6841
6989
  };
6842
6990
 
6843
- const className = mergeClassNames(Viewlet, Search$3);
6991
+ const className = mergeClassNames(Viewlet, Search$2);
6844
6992
  const getSearchVirtualDom = (visibleItems, flags, message, focusOutline, searchInputErrorMessage, scrollBarHeight, scrollBarY, scrollBarValue, deltaY, itemHeight, matchCount, limitHitWarning, focus = 0, initial = false, isSearchEditor = false, contextLines = 1, contextLinesEnabled = false, workspacePath) => {
6845
6993
  if (initial) {
6846
6994
  return [];
@@ -6863,8 +7011,11 @@ const getDom = newState => {
6863
7011
 
6864
7012
  // TODO cache rendered dom so that it can be used for dom diffing
6865
7013
  const renderIncremental = (oldState, newState) => {
6866
- const oldDom = getDom(oldState);
6867
7014
  const newDom = getDom(newState);
7015
+ if (oldState.replacement !== newState.replacement) {
7016
+ return [SetDom2, newState.uid, newDom];
7017
+ }
7018
+ const oldDom = getDom(oldState);
6868
7019
  const patches = diffTree(oldDom, newDom);
6869
7020
  return [SetPatches, newState.uid, patches];
6870
7021
  };
@@ -6926,6 +7077,9 @@ const applyRender = (oldState, newState, diffResult) => {
6926
7077
  const renderDirect = async (uid, commands) => {
6927
7078
  const rendererWorkerCommands = commands.filter(command => command[0] === SetFocusContext);
6928
7079
  const rendererProcessCommands = commands.filter(command => command[0] !== SetFocusContext);
7080
+ if (rendererProcessCommands.length === 0) {
7081
+ return rendererWorkerCommands;
7082
+ }
6929
7083
  const transactionId = await invoke('Viewlet.queueCommands', uid, rendererProcessCommands);
6930
7084
  return [...rendererWorkerCommands, ['Viewlet.commitPending', uid, transactionId]];
6931
7085
  };
@@ -7036,7 +7190,7 @@ const getActions = state => {
7036
7190
  type: Button
7037
7191
  }, {
7038
7192
  command: '',
7039
- enabled: hasSearchResults,
7193
+ enabled: true,
7040
7194
  icon: ListFlat,
7041
7195
  id: ViewAsTree,
7042
7196
  label: viewAsTree$1(),
@@ -7145,19 +7299,6 @@ const rerender = state => {
7145
7299
  };
7146
7300
  };
7147
7301
 
7148
- const revealInExplorerActual = async uri => {
7149
- await invoke$3('SideBar.show', 'Explorer');
7150
- const states = await invoke$3('Viewlet.getAllStates');
7151
- const viewlets = Object.values(states);
7152
- const sideBar = viewlets.find(viewlet => viewlet.currentViewletId === 'Explorer');
7153
- const explorerUid = Math.max(...viewlets.filter(viewlet => viewlet.parentUid === sideBar.uid).map(viewlet => viewlet.uid));
7154
- await invoke$3('Viewlet.executeViewletCommand', explorerUid, 'reveal', uri);
7155
- };
7156
- const revealInExplorer = async (state, uri) => {
7157
- await revealInExplorerActual(uri);
7158
- return state;
7159
- };
7160
-
7161
7302
  const saveState = state => {
7162
7303
  const {
7163
7304
  collapsedPaths,
@@ -7249,6 +7390,23 @@ const focusReplaceAll = state => {
7249
7390
  return focusElement(state, FocusSearchReplaceAll);
7250
7391
  };
7251
7392
 
7393
+ const applyComponentState = (currentState, state) => {
7394
+ if (!state || typeof state !== 'object' || Array.isArray(state)) {
7395
+ throw new TypeError('Text Search state must be an object');
7396
+ }
7397
+ const {
7398
+ uid
7399
+ } = state;
7400
+ const {
7401
+ uid: currentUid
7402
+ } = currentState;
7403
+ if (uid !== currentUid) {
7404
+ throw new Error(`Text Search state uid must remain ${currentUid}`);
7405
+ }
7406
+ return state;
7407
+ };
7408
+ const setComponentState = wrapCommand(applyComponentState);
7409
+
7252
7410
  const setLimit = (state, limit) => {
7253
7411
  return handleUpdate(state, {
7254
7412
  limit
@@ -7261,6 +7419,7 @@ const getNewHistory = (history, newValue) => {
7261
7419
  const cutHistory = newHistory.slice(0, maxHistoryLength);
7262
7420
  return cutHistory;
7263
7421
  };
7422
+
7264
7423
  const submit = state => {
7265
7424
  const {
7266
7425
  history,
@@ -7374,22 +7533,23 @@ const commandMap$1 = {
7374
7533
  'TextSearch.focusSearchValue': wrapCommand(focusSearchValue$1),
7375
7534
  'TextSearch.focusSearchValueNext': wrapCommand(focusSearchValueNext),
7376
7535
  'TextSearch.getCommandIds': getCommandIds,
7536
+ 'TextSearch.getComponentState': getComponentState,
7377
7537
  'TextSearch.getKeyBindings': getKeyBindings,
7378
7538
  'TextSearch.getMenuEntries': wrapGetter(getMenuEntries),
7379
7539
  'TextSearch.getMenuEntryIds': getMenuEntryIds,
7380
7540
  'TextSearch.handleActionClick': wrapCommand(handleActionClick),
7381
7541
  'TextSearch.handleClickAt': wrapCommand(handleClickAt),
7382
7542
  'TextSearch.handleContextMenu': wrapCommand(handleContextMenu),
7383
- 'TextSearch.handleExcludeInput': wrapCommand(handleExcludeInput),
7543
+ 'TextSearch.handleExcludeInput': wrapSerialCommand(handleExcludeInput),
7384
7544
  'TextSearch.handleFocusIn': wrapCommand(handleFocusIn),
7385
7545
  'TextSearch.handleHeaderClick': wrapCommand(handleHeaderClick),
7386
7546
  'TextSearch.handleHeaderContextMenu': wrapCommand(handleHeaderContextMenu),
7387
7547
  'TextSearch.handleHeaderFocusIn': wrapCommand(handleHeaderFocusIn),
7388
7548
  'TextSearch.handleHeaderFocusOut': wrapCommand(handleHeaderFocusOut),
7389
7549
  'TextSearch.handleIconThemeChange': wrapCommand(handleIconThemeChange),
7390
- 'TextSearch.handleIncludeInput': wrapCommand(handleIncludeInput),
7391
- 'TextSearch.handleInput': wrapCommand(handleInput),
7392
- 'TextSearch.handleInput2': wrapCommand(handleInput2),
7550
+ 'TextSearch.handleIncludeInput': wrapSerialCommand(handleIncludeInput),
7551
+ 'TextSearch.handleInput': wrapSerialCommand(handleInput),
7552
+ 'TextSearch.handleInput2': wrapSerialCommand(handleInput2),
7393
7553
  'TextSearch.handleInputBlur': wrapCommand(handleInputBlur),
7394
7554
  'TextSearch.handleInputContextMenu': wrapCommand(handleInputContextMenu),
7395
7555
  'TextSearch.handleInputCopy': wrapCommand(handleInputCopy),
@@ -7404,7 +7564,7 @@ const commandMap$1 = {
7404
7564
  'TextSearch.handleMessagePort': handleDirectMessagePort,
7405
7565
  'TextSearch.handleOpenFolderClick': wrapCommand(handleOpenFolderClick),
7406
7566
  'TextSearch.handlePullResultsFound': wrapCommand(handlePullResultsFound),
7407
- 'TextSearch.handleReplaceInput': wrapCommand(handleReplaceInput),
7567
+ 'TextSearch.handleReplaceInput': wrapSerialCommand(handleReplaceInput),
7408
7568
  'TextSearch.handleResize': wrapCommand(handleResize),
7409
7569
  'TextSearch.handleScrollBarCaptureLost': wrapCommand(handleScrollBarCaptureLost),
7410
7570
  'TextSearch.handleScrollBarClick': wrapCommand(handleScrollBarClick),
@@ -7413,9 +7573,9 @@ const commandMap$1 = {
7413
7573
  'TextSearch.handleWheel': wrapCommand(handleWheel),
7414
7574
  'TextSearch.handleWorkspaceChange': wrapCommand(handleWorkspaceChange),
7415
7575
  'TextSearch.loadContent': wrapCommand(loadContent),
7416
- 'TextSearch.nextHistoryResult': wrapCommand(nextHistoryResult),
7576
+ 'TextSearch.nextHistoryResult': wrapSerialCommand(nextHistoryResult),
7417
7577
  'TextSearch.openSearchEditor': wrapCommand(openSearchEditor),
7418
- 'TextSearch.previousHistoryResult': wrapCommand(previousHistoryResult),
7578
+ 'TextSearch.previousHistoryResult': wrapSerialCommand(previousHistoryResult),
7419
7579
  'TextSearch.refresh': wrapCommand(refresh),
7420
7580
  'TextSearch.removeCurrent': wrapCommand(removeCurrent),
7421
7581
  'TextSearch.removeIndex': wrapCommand(removeIndex),
@@ -7429,21 +7589,21 @@ const commandMap$1 = {
7429
7589
  'TextSearch.replaceAllInFile': wrapCommand(replaceAllInFile),
7430
7590
  'TextSearch.rerender': rerender,
7431
7591
  'TextSearch.restoreState': restoreState,
7432
- 'TextSearch.revealInExplorer': wrapCommand(revealInExplorer),
7433
7592
  'TextSearch.saveState': wrapGetter(saveState),
7434
7593
  'TextSearch.selectIndex': wrapCommand(selectIndex),
7435
- 'TextSearch.setLimit': wrapCommand(setLimit),
7436
- 'TextSearch.submit': wrapCommand(submit),
7594
+ 'TextSearch.setComponentState': setComponentState,
7595
+ 'TextSearch.setLimit': wrapSerialCommand(setLimit),
7596
+ 'TextSearch.submit': wrapSerialCommand(submit),
7437
7597
  'TextSearch.terminate': terminate,
7438
7598
  'TextSearch.textSearch': textSearch,
7439
- 'TextSearch.toggleMatchCase': wrapCommand(toggleMatchCase),
7440
- 'TextSearch.toggleMatchWholeWord': wrapCommand(toggleMatchWholeWord),
7441
- 'TextSearch.toggleOpenEditors': wrapCommand(toggleOpenEditors),
7599
+ 'TextSearch.toggleMatchCase': wrapSerialCommand(toggleMatchCase),
7600
+ 'TextSearch.toggleMatchWholeWord': wrapSerialCommand(toggleMatchWholeWord),
7601
+ 'TextSearch.toggleOpenEditors': wrapSerialCommand(toggleOpenEditors),
7442
7602
  'TextSearch.togglePreserveCase': wrapCommand(togglePreserveCase),
7443
- 'TextSearch.toggleReplace': wrapCommand(toggleReplace),
7603
+ 'TextSearch.toggleReplace': wrapSerialCommand(toggleReplace),
7444
7604
  'TextSearch.toggleSearchDetails': wrapCommand(toggleDetailsExpanded),
7445
- 'TextSearch.toggleUseIgnoreFiles': wrapCommand(toggleUseIgnoreFiles),
7446
- 'TextSearch.toggleUseRegularExpression': wrapCommand(toggleUseRegularExpression),
7605
+ 'TextSearch.toggleUseIgnoreFiles': wrapSerialCommand(toggleUseIgnoreFiles),
7606
+ 'TextSearch.toggleUseRegularExpression': wrapSerialCommand(toggleUseRegularExpression),
7447
7607
  'TextSearch.viewAsTree': wrapCommand(viewAsTree)
7448
7608
  };
7449
7609
 
@@ -7491,7 +7651,7 @@ const initializeTextMeasurementWorker = async () => {
7491
7651
  commandMap: {},
7492
7652
  send: send$1
7493
7653
  });
7494
- set$2(rpc);
7654
+ set$4(rpc);
7495
7655
  };
7496
7656
 
7497
7657
  const commandMap = {
@@ -7510,7 +7670,7 @@ const launchTextSearchWorker = async () => {
7510
7670
 
7511
7671
  const initializeTextSearchWorker = async () => {
7512
7672
  const rpc = await launchTextSearchWorker();
7513
- set$3(rpc);
7673
+ set$2(rpc);
7514
7674
  };
7515
7675
 
7516
7676
  const listen = async () => {
@@ -7518,7 +7678,7 @@ const listen = async () => {
7518
7678
  const rpc = await create$4({
7519
7679
  commandMap: commandMap$1
7520
7680
  });
7521
- set$4(rpc);
7681
+ set$3(rpc);
7522
7682
  await Promise.all([initializeClipBoardWorker(), initializeDialogWorker(), initializeIconThemeWorker(), initializeTextMeasurementWorker(), initializeTextSearchWorker()]);
7523
7683
  };
7524
7684