@lvce-editor/source-control-worker 2.14.0 → 2.16.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.
@@ -1229,161 +1229,435 @@ const terminate = () => {
1229
1229
  globalThis.close();
1230
1230
  };
1231
1231
 
1232
- const {
1233
- get: get$1,
1234
- set,
1235
- wrapCommand,
1236
- getCommandIds,
1237
- registerCommands,
1238
- wrapGetter
1239
- } = create();
1240
-
1241
- const create2 = (id, uri, x, y, width, height, workspacePath) => {
1242
- const state = {
1243
- actionsCache: Object.create(null),
1244
- allGroups: [],
1245
- deltaY: 0,
1246
- enabledProviderIds: [],
1247
- fileIconCache: Object.create(null),
1248
- finalDeltaY: 0,
1249
- gitRoot: '',
1250
- handleOffset: 0,
1251
- headerHeight: 40,
1252
- // TODO
1253
- height,
1254
- id,
1255
- index: [],
1256
- inputValue: '',
1257
- expandedGroups: Object.create(null),
1258
- itemHeight: 20,
1259
- items: [],
1260
- maxLineY: 0,
1261
- merge: [],
1262
- minimumSliderSize: 20,
1263
- inputBoxHeight: 30,
1264
- minLineY: 0,
1265
- providerId: '',
1266
- root: '',
1267
- scrollBarActive: false,
1268
- scrollBarHeight: 0,
1269
- splitButtonEnabled: false,
1270
- untracked: [],
1271
- visibleItems: [],
1272
- width,
1273
- workingTree: [],
1274
- workspacePath,
1275
- x,
1276
- y,
1277
- inputPlaceholder: '',
1278
- inputSource: 0,
1279
- maxInputLines: 5,
1280
- inputFontFamily: 'system-ui, Ubuntu, "Droid Sans", sans-serif',
1281
- inputFontSize: 13,
1282
- inputFontWeight: 400,
1283
- inputLetterSpacing: 0,
1284
- inputLineHeight: 20,
1285
- inputBoxMaxHeight: 214,
1286
- history: [],
1287
- viewMode: 1,
1288
- iconDefinitions: [],
1289
- decorationIcons: [],
1290
- focus: 0
1291
- };
1292
- set(id, state, state);
1232
+ const getActualDecorationIcon = (iconDefinitions, icon) => {
1233
+ if (typeof icon === 'number') {
1234
+ const value = iconDefinitions[icon];
1235
+ if (!value) {
1236
+ return 'not-available';
1237
+ }
1238
+ return value;
1239
+ }
1240
+ return icon;
1293
1241
  };
1294
1242
 
1295
- const isEqual$3 = (oldState, newState) => {
1296
- return oldState.inputBoxHeight === newState.inputBoxHeight;
1243
+ const getFileIcon = ({
1244
+ name
1245
+ }) => {
1246
+ return '';
1297
1247
  };
1298
1248
 
1299
- const isEqual$2 = (oldState, newState) => {
1300
- return oldState.focus === newState.focus;
1249
+ // TODO this should be in FileSystem module
1250
+ const pathBaseName = path => {
1251
+ return path.slice(path.lastIndexOf('/') + 1);
1301
1252
  };
1302
1253
 
1303
- const isEqual$1 = (oldState, newState) => {
1304
- return oldState.allGroups === newState.allGroups && oldState.deltaY === newState.deltaY && oldState.items === newState.items && oldState.maxLineY === newState.maxLineY && oldState.minLineY === newState.minLineY && oldState.visibleItems === newState.visibleItems;
1254
+ const getDisplayItemsGroup = (group, expandedGroups, iconDefinitions) => {
1255
+ const displayItems = [];
1256
+ const {
1257
+ id,
1258
+ label,
1259
+ items
1260
+ } = group;
1261
+ if (!items) {
1262
+ throw new Error('Source control group is missing an items property');
1263
+ }
1264
+ const {
1265
+ length
1266
+ } = items;
1267
+ const isExpanded = expandedGroups[id] || false;
1268
+ const type = isExpanded ? DirectoryExpanded : Directory;
1269
+ const icon = isExpanded ? 'ChevronDown' : 'ChevronRight';
1270
+ if (length > 0) {
1271
+ displayItems.push({
1272
+ file: '',
1273
+ label,
1274
+ detail: '',
1275
+ posInSet: 1,
1276
+ setSize: 1,
1277
+ icon,
1278
+ decorationIcon: '',
1279
+ decorationIconTitle: '',
1280
+ decorationStrikeThrough: false,
1281
+ type,
1282
+ badgeCount: length,
1283
+ groupId: id
1284
+ });
1285
+ }
1286
+ if (isExpanded) {
1287
+ for (let i = 0; i < length; i++) {
1288
+ const item = items[i];
1289
+ const {
1290
+ file,
1291
+ icon,
1292
+ iconTitle,
1293
+ strikeThrough
1294
+ } = item;
1295
+ const baseName = pathBaseName(file);
1296
+ const folderName = file.slice(0, -baseName.length - 1);
1297
+ const actualDecorationIcon = getActualDecorationIcon(iconDefinitions, icon);
1298
+ displayItems.push({
1299
+ file,
1300
+ label: baseName,
1301
+ detail: folderName,
1302
+ posInSet: i + 1,
1303
+ setSize: length,
1304
+ icon: getFileIcon({
1305
+ name: file
1306
+ }),
1307
+ decorationIcon: actualDecorationIcon,
1308
+ decorationIconTitle: iconTitle,
1309
+ decorationStrikeThrough: strikeThrough,
1310
+ type: File,
1311
+ badgeCount: 0,
1312
+ groupId: id
1313
+ });
1314
+ }
1315
+ }
1316
+ return displayItems;
1305
1317
  };
1306
1318
 
1307
- const RenderItems = 4;
1308
- const RenderFocus = 6;
1309
- const RenderFocusContext = 7;
1310
- const RenderValue = 8;
1311
- const RenderCss = 10;
1312
-
1313
- const isEqual = (oldState, newState) => {
1314
- return newState.inputSource === User || oldState.inputValue === newState.inputValue;
1319
+ const getDisplayItems = (allGroups, expandedGroups, iconDefinitions) => {
1320
+ const displayItems = [];
1321
+ for (const group of allGroups) {
1322
+ const groupDisplayItems = getDisplayItemsGroup(group, expandedGroups, iconDefinitions);
1323
+ displayItems.push(...groupDisplayItems);
1324
+ }
1325
+ return displayItems;
1315
1326
  };
1316
1327
 
1317
- const modules = [isEqual$1, isEqual, isEqual$3, isEqual$2];
1318
- const numbers = [RenderItems, RenderValue, RenderCss, RenderFocus];
1328
+ const getIconType = direntType => {
1329
+ switch (direntType) {
1330
+ case Directory:
1331
+ case DirectoryExpanded:
1332
+ return 2;
1333
+ default:
1334
+ return 1;
1335
+ }
1336
+ };
1319
1337
 
1320
- const diff = (oldState, newState) => {
1321
- const diffResult = [];
1322
- for (let i = 0; i < modules.length; i++) {
1323
- const fn = modules[i];
1324
- if (!fn(oldState, newState)) {
1325
- diffResult.push(numbers[i]);
1338
+ const getMissingIconRequests = (dirents, fileIconCache) => {
1339
+ const missingRequests = [];
1340
+ for (const dirent of dirents) {
1341
+ if (!(dirent.file in fileIconCache)) {
1342
+ missingRequests.push({
1343
+ type: getIconType(dirent.type),
1344
+ name: dirent.label
1345
+ });
1326
1346
  }
1327
1347
  }
1328
- return diffResult;
1348
+ return missingRequests;
1329
1349
  };
1330
1350
 
1331
- const diff2 = uid => {
1332
- const {
1333
- oldState,
1334
- newState
1335
- } = get$1(uid);
1336
- const result = diff(oldState, newState);
1337
- return result;
1351
+ const requestFileIcons = async requests => {
1352
+ const results = await invoke('IconTheme.getIcons', requests);
1353
+ return results;
1338
1354
  };
1339
1355
 
1340
- const getInfo = uid => {
1341
- const {
1342
- newState
1343
- } = get$1(uid);
1344
- return newState.allGroups;
1356
+ const updateIconCache = (iconCache, missingRequests, newIcons) => {
1357
+ if (missingRequests.length === 0) {
1358
+ return iconCache;
1359
+ }
1360
+ const newFileIconCache = {
1361
+ ...iconCache
1362
+ };
1363
+ for (let i = 0; i < missingRequests.length; i++) {
1364
+ const request = missingRequests[i];
1365
+ const icon = newIcons[i];
1366
+ newFileIconCache[request.name] = icon;
1367
+ }
1368
+ return newFileIconCache;
1345
1369
  };
1346
1370
 
1347
- const mergeClassNames = (...classNames) => {
1348
- return classNames.filter(Boolean).join(' ');
1371
+ const getFileIcons = async (dirents, fileIconCache) => {
1372
+ const missingRequests = getMissingIconRequests(dirents, fileIconCache);
1373
+ const newIcons = await requestFileIcons(missingRequests);
1374
+ const newFileIconCache = updateIconCache(fileIconCache, missingRequests, newIcons);
1375
+ return newFileIconCache;
1349
1376
  };
1350
1377
 
1351
- const text = data => {
1352
- return {
1353
- type: Text,
1354
- text: data,
1355
- childCount: 0
1356
- };
1378
+ const getFinalDeltaY = (height, itemHeight, itemsLength) => {
1379
+ const contentHeight = itemsLength * itemHeight;
1380
+ const finalDeltaY = Math.max(contentHeight - height, 0);
1381
+ return finalDeltaY;
1357
1382
  };
1358
1383
 
1359
- const getKeyBindings = () => {
1360
- return [{
1361
- key: CtrlCmd | Enter,
1362
- command: 'Source Control.acceptInput',
1363
- when: FocusSourceControlInput
1364
- }];
1384
+ const activateByEvent = event => {
1385
+ return activateByEvent$1(event);
1365
1386
  };
1366
1387
 
1367
- const emptyObject = {};
1368
- const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1369
- const i18nString = (key, placeholders = emptyObject) => {
1370
- if (placeholders === emptyObject) {
1371
- return key;
1372
- }
1373
- const replacer = (match, rest) => {
1374
- return placeholders[rest];
1375
- };
1376
- return key.replaceAll(RE_PLACEHOLDER, replacer);
1388
+ const executeProvider = async ({
1389
+ event,
1390
+ method,
1391
+ params
1392
+ }) => {
1393
+ await activateByEvent(event);
1394
+ // @ts-ignore
1395
+ const result = await invoke$1(method, ...params);
1396
+ return result;
1377
1397
  };
1378
1398
 
1379
- const OpenChanges = 'Open Changes';
1380
- const OpenFile = 'Open File';
1399
+ const CommandExecute = 'ExtensionHostCommand.executeCommand';
1400
+ const SourceControlAcceptInput = 'ExtensionHostSourceControl.acceptInput';
1401
+ const SourceControlGetFileDecorations = 'ExtensionHostSourceControl.getFileDecorations';
1402
+ const SourceControlGetEnabledProviderIds = 'ExtensionHostSourceControl.getEnabledProviderIds';
1403
+ const SourceControlGetFileBefore = 'ExtensionHostSourceControl.getFileBefore';
1404
+ const SourceControlGetGroups = 'ExtensionHostSourceControl.getGroups';
1405
+
1406
+ const acceptInput$2 = async (providerId, text) => {
1407
+ return executeProvider({
1408
+ event: 'none',
1409
+ method: SourceControlAcceptInput,
1410
+ params: [providerId, text]
1411
+ // noProviderFoundMessage: 'No source control provider found',
1412
+ });
1413
+ };
1414
+ const getFileDecorations$1 = (providerId, uris) => {
1415
+ return executeProvider({
1416
+ event: 'none',
1417
+ method: SourceControlGetFileDecorations,
1418
+ params: [providerId, uris]
1419
+ });
1420
+ };
1421
+ const getFileBefore$1 = (providerId, path) => {
1422
+ return executeProvider({
1423
+ event: 'none',
1424
+ method: SourceControlGetFileBefore,
1425
+ params: [providerId, path]
1426
+ // noProviderFoundMessage: 'No source control provider found',
1427
+ });
1428
+ };
1429
+ const getGroups$2 = (providerId, path) => {
1430
+ return executeProvider({
1431
+ event: 'none',
1432
+ method: SourceControlGetGroups,
1433
+ params: [providerId, path]
1434
+ // noProviderFoundMessage: 'No source control provider found',
1435
+ });
1436
+ };
1437
+ const getEnabledProviderIds$1 = (scheme, root) => {
1438
+ return executeProvider({
1439
+ event: `onSourceControl:${scheme}`,
1440
+ method: SourceControlGetEnabledProviderIds,
1441
+ params: [scheme, root]
1442
+ // noProviderFoundMessage: 'No source control provider found',
1443
+ });
1444
+ };
1445
+ const getIconDefinitions$1 = async providerId => {
1446
+ // @ts-ignore
1447
+ const result = await invoke$1('ExtensionHostSourceControl.getIconDefinitions', providerId);
1448
+ return result;
1449
+ };
1450
+
1451
+ const acceptInput$1 = (providerId, text) => {
1452
+ string(providerId);
1453
+ string(text);
1454
+ return acceptInput$2(providerId, text);
1455
+ };
1456
+ const getFileDecorations = (providerId, uris) => {
1457
+ return getFileDecorations$1(providerId, uris);
1458
+ };
1459
+ const getFileBefore = (providerId, file) => {
1460
+ return getFileBefore$1(providerId, file);
1461
+ };
1462
+ const getEnabledProviderIds = (scheme, root) => {
1463
+ string(scheme);
1464
+ string(root);
1465
+ return getEnabledProviderIds$1(scheme, root);
1466
+ };
1467
+ const getGroups$1 = (providerId, root) => {
1468
+ return getGroups$2(providerId, root);
1469
+ };
1470
+ const getIconDefinitions = async providerIds => {
1471
+ try {
1472
+ if (providerIds.length === 0) {
1473
+ return [];
1474
+ }
1475
+ return await getIconDefinitions$1(providerIds[0]);
1476
+ } catch {
1477
+ return [];
1478
+ }
1479
+ };
1480
+
1481
+ const getGroups = async enabledProviderIds => {
1482
+ const allGroups = [];
1483
+ for (const providerId of enabledProviderIds) {
1484
+ // @ts-ignore
1485
+ const groups = await getGroups$1(providerId);
1486
+ allGroups.push(...groups);
1487
+ }
1488
+ return {
1489
+ allGroups,
1490
+ gitRoot: ''
1491
+ };
1492
+ };
1493
+
1494
+ const getTextHeight = async (input, width, fontFamily, fontSize, fontWeight, letterSpacing, lineHeight) => {
1495
+ try {
1496
+ if (!input) {
1497
+ return lineHeight;
1498
+ }
1499
+ const actualInput = input;
1500
+ // TODO line height could also be like 1.5
1501
+ const lineHeightPx = `${lineHeight}px`;
1502
+ // @ts-ignore
1503
+ const height = await invoke(`MeasureTextHeight.measureTextBlockHeight`, actualInput, fontFamily, fontSize, lineHeightPx, width);
1504
+ return height;
1505
+ } catch {
1506
+ // fallback
1507
+ const lines = input.split('\n');
1508
+ const lineCount = lines.length;
1509
+ const inputHeight = lineCount * lineHeight;
1510
+ return inputHeight;
1511
+ }
1512
+ };
1513
+
1514
+ const getInputHeight = async (input, width, fontFamily, fontWeight, fontSize, letterSpacing, lineHeight) => {
1515
+ const height = await getTextHeight(input, width, fontFamily, fontSize, fontWeight, letterSpacing, lineHeight);
1516
+ return height;
1517
+ };
1518
+
1519
+ const getListHeight = (itemsLength, itemHeight, maxHeight) => {
1520
+ number(itemsLength);
1521
+ number(itemHeight);
1522
+ number(maxHeight);
1523
+ if (itemsLength === 0) {
1524
+ return itemHeight;
1525
+ }
1526
+ const totalHeight = itemsLength * itemHeight;
1527
+ return Math.min(totalHeight, maxHeight);
1528
+ };
1529
+
1530
+ // TODO optimize this function to return the minimum number
1531
+ // of visible items needed, e.g. when not scrolled 5 items with
1532
+ // 20px fill 100px but when scrolled 6 items are needed
1533
+ const getNumberOfVisibleItems = (listHeight, itemHeight) => {
1534
+ return Math.ceil(listHeight / itemHeight) + 1;
1535
+ };
1536
+
1537
+ const Disk = 'file';
1538
+
1539
+ const RE_PROTOCOL = /^([a-z-]+):\/\//;
1540
+ const getProtocol = uri => {
1541
+ if (!uri) {
1542
+ return Disk;
1543
+ }
1544
+ const protocolMatch = uri.match(RE_PROTOCOL);
1545
+ if (protocolMatch) {
1546
+ return protocolMatch[1];
1547
+ }
1548
+ return Disk;
1549
+ };
1550
+
1551
+ const emptySourceControlButtons = [];
1552
+
1553
+ const getContextId = (groupId, type) => {
1554
+ if (type === File) {
1555
+ return `${groupId}-item`;
1556
+ }
1557
+ return groupId;
1558
+ };
1559
+
1560
+ const defaultIndent = 16; // 1rem = 16px
1561
+
1562
+ const getTreeItemIndent = type => {
1563
+ if (type === Directory || type === DirectoryExpanded) {
1564
+ return 0;
1565
+ }
1566
+ return defaultIndent;
1567
+ };
1568
+
1569
+ const getVisibleSourceControlItems = (items, minLineY, maxLineY, actionsCache, fileIconCache) => {
1570
+ const visible = [];
1571
+ for (let i = minLineY; i < maxLineY; i++) {
1572
+ const item = items[i];
1573
+ const contextId = getContextId(item.groupId, item.type);
1574
+ const buttons = actionsCache[contextId] || emptySourceControlButtons;
1575
+ const fileIcon = fileIconCache[item.label] || '';
1576
+ const indent = getTreeItemIndent(item.type);
1577
+ visible.push({
1578
+ ...item,
1579
+ buttons,
1580
+ fileIcon,
1581
+ indent
1582
+ });
1583
+ }
1584
+ return visible;
1585
+ };
1586
+
1587
+ const get$1 = key => {
1588
+ return getPreference(key);
1589
+ };
1590
+
1591
+ const getExtensions = async () => {
1592
+ return invoke$1('Extensions.getExtensions');
1593
+ };
1594
+
1595
+ const requestSourceActions = async () => {
1596
+ const extensions = await getExtensions();
1597
+ const newCache = Object.create(null);
1598
+ for (const extension of extensions) {
1599
+ if (extension && extension['source-control-actions']) {
1600
+ for (const [key, value] of Object.entries(extension['source-control-actions'])) {
1601
+ newCache[key] = value;
1602
+ }
1603
+ }
1604
+ }
1605
+ return newCache;
1606
+ };
1607
+
1608
+ /* eslint-disable unicorn/no-array-reduce */
1609
+ const restoreExpandedGroups = groups => {
1610
+ return groups.map(group => group.id).reduce((total, current) => {
1611
+ return {
1612
+ ...total,
1613
+ [current]: true
1614
+ };
1615
+ }, Object.create(null));
1616
+ };
1617
+
1618
+ const getRestoredInputValue = savedState => {
1619
+ if (savedState && typeof savedState === 'object' && 'inputValue' in savedState && typeof savedState['inputValue'] === 'string') {
1620
+ return savedState.inputValue;
1621
+ }
1622
+ return '';
1623
+ };
1624
+ const restoreState = savedState => {
1625
+ const inputValue = getRestoredInputValue(savedState);
1626
+ return {
1627
+ inputValue
1628
+ };
1629
+ };
1630
+
1631
+ const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
1632
+ if (size >= contentSize) {
1633
+ return 0;
1634
+ }
1635
+ return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
1636
+ };
1637
+
1638
+ const emptyObject = {};
1639
+ const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1640
+ const i18nString = (key, placeholders = emptyObject) => {
1641
+ if (placeholders === emptyObject) {
1642
+ return key;
1643
+ }
1644
+ const replacer = (match, rest) => {
1645
+ return placeholders[rest];
1646
+ };
1647
+ return key.replaceAll(RE_PLACEHOLDER, replacer);
1648
+ };
1649
+
1650
+ const OpenChanges = 'Open Changes';
1651
+ const OpenFile = 'Open File';
1381
1652
  const OpenFileHead = 'Open File (HEAD)';
1382
1653
  const DiscardChanges = 'Discard Changes';
1383
1654
  const StageChanges = 'Stage Changes';
1384
1655
  const AddToGitignore = 'Add to gitignore';
1385
1656
  const RevealInExplorerView = 'Reveal in Explorer View';
1386
1657
  const OpenContainingFolder = 'Open Containing Folder';
1658
+ const ViewAsTree$1 = 'View As Tree';
1659
+ const CommitAndPush$1 = 'Commit and Push';
1660
+ const Refresh$2 = 'Refresh';
1387
1661
  const MessageEnterToCommitOnMaster = `Message (Enter) to commit on 'master'`;
1388
1662
  const SourceControlInput$1 = 'Source Control Input';
1389
1663
 
@@ -1411,6 +1685,15 @@ const revealInExplorerView = () => {
1411
1685
  const openContainingFolder = () => {
1412
1686
  return i18nString(OpenContainingFolder);
1413
1687
  };
1688
+ const viewAsTree$1 = () => {
1689
+ return i18nString(ViewAsTree$1);
1690
+ };
1691
+ const commitAndPush = () => {
1692
+ return i18nString(CommitAndPush$1);
1693
+ };
1694
+ const refresh$1 = () => {
1695
+ return i18nString(Refresh$2);
1696
+ };
1414
1697
  const messageEnterToCommitOnMaster = () => {
1415
1698
  return i18nString(MessageEnterToCommitOnMaster);
1416
1699
  };
@@ -1418,478 +1701,313 @@ const sourceControlInput = () => {
1418
1701
  return i18nString(SourceControlInput$1);
1419
1702
  };
1420
1703
 
1421
- const getMenuEntries = () => {
1422
- return [{
1423
- label: openChanges(),
1424
- flags: None,
1425
- command: /* TODO */'-1',
1426
- id: ''
1427
- }, {
1428
- label: openFile(),
1429
- flags: None,
1430
- command: /* TODO */'-1',
1431
- id: ''
1432
- }, {
1433
- label: openFileHead(),
1434
- flags: None,
1435
- command: /* TODO */'-1',
1436
- id: ''
1437
- }, {
1438
- label: discardChanges(),
1439
- flags: None,
1440
- command: /* TODO */'-1',
1441
- id: ''
1442
- }, {
1443
- label: stageChanges(),
1444
- flags: None,
1445
- command: /* TODO */'-1',
1446
- id: ''
1447
- }, {
1448
- label: addToGitignore(),
1449
- flags: None,
1450
- command: /* TODO */'-1',
1451
- id: ''
1452
- }, {
1453
- label: revealInExplorerView(),
1454
- flags: None,
1455
- command: /* TODO */'-1',
1456
- id: ''
1457
- }, {
1458
- label: openContainingFolder(),
1459
- flags: None,
1460
- command: /* TODO */'-1',
1461
- id: ''
1462
- }];
1463
- };
1464
-
1465
- const getMenuEntries2 = state => {
1466
- return getMenuEntries();
1467
- };
1468
-
1469
- const getMenuIds = () => {
1470
- return [SourceControl$1];
1471
- };
1472
-
1473
- const activateByEvent = event => {
1474
- return activateByEvent$1(event);
1475
- };
1476
-
1477
- const executeProvider = async ({
1478
- event,
1479
- method,
1480
- params
1481
- }) => {
1482
- await activateByEvent(event);
1483
- // @ts-ignore
1484
- const result = await invoke$1(method, ...params);
1485
- return result;
1486
- };
1487
-
1488
- const CommandExecute = 'ExtensionHostCommand.executeCommand';
1489
- const SourceControlGetFileDecorations = 'ExtensionHostSourceControl.getFileDecorations';
1490
- const SourceControlGetEnabledProviderIds = 'ExtensionHostSourceControl.getEnabledProviderIds';
1491
- const SourceControlGetFileBefore = 'ExtensionHostSourceControl.getFileBefore';
1492
- const SourceControlGetGroups = 'ExtensionHostSourceControl.getGroups';
1493
-
1494
- const executeCommand = (id, ...args) => {
1495
- return executeProvider({
1496
- event: `onCommand:${id}`,
1497
- method: CommandExecute,
1498
- params: [id, ...args]
1499
- });
1500
- };
1501
-
1502
- const getActualDecorationIcon = (iconDefinitions, icon) => {
1503
- if (typeof icon === 'number') {
1504
- const value = iconDefinitions[icon];
1505
- if (!value) {
1506
- return 'not-available';
1507
- }
1508
- return value;
1509
- }
1510
- return icon;
1511
- };
1512
-
1513
- const getFileIcon = ({
1514
- name
1515
- }) => {
1516
- return '';
1517
- };
1518
-
1519
- // TODO this should be in FileSystem module
1520
- const pathBaseName = path => {
1521
- return path.slice(path.lastIndexOf('/') + 1);
1522
- };
1523
-
1524
- const getDisplayItemsGroup = (group, expandedGroups, iconDefinitions) => {
1525
- const displayItems = [];
1704
+ const loadContent = async (state, savedState) => {
1526
1705
  const {
1527
- id,
1528
- label,
1529
- items
1530
- } = group;
1531
- if (!items) {
1532
- throw new Error('Source control group is missing an items property');
1533
- }
1706
+ itemHeight,
1707
+ height,
1708
+ minimumSliderSize,
1709
+ workspacePath,
1710
+ fileIconCache,
1711
+ width,
1712
+ inputFontFamily,
1713
+ inputFontSize,
1714
+ inputFontWeight,
1715
+ inputLetterSpacing,
1716
+ inputLineHeight
1717
+ } = state;
1718
+ const root = workspacePath;
1719
+ const scheme = getProtocol(root);
1534
1720
  const {
1535
- length
1536
- } = items;
1537
- const isExpanded = expandedGroups[id] || false;
1538
- const type = isExpanded ? DirectoryExpanded : Directory;
1539
- const icon = isExpanded ? 'ChevronDown' : 'ChevronRight';
1540
- if (length > 0) {
1541
- displayItems.push({
1542
- file: '',
1543
- label,
1544
- detail: '',
1545
- posInSet: 1,
1546
- setSize: 1,
1547
- icon,
1548
- decorationIcon: '',
1549
- decorationIconTitle: '',
1550
- decorationStrikeThrough: false,
1551
- type,
1552
- badgeCount: length,
1553
- groupId: id
1554
- });
1555
- }
1556
- if (isExpanded) {
1557
- for (let i = 0; i < length; i++) {
1558
- const item = items[i];
1559
- const {
1560
- file,
1561
- icon,
1562
- iconTitle,
1563
- strikeThrough
1564
- } = item;
1565
- const baseName = pathBaseName(file);
1566
- const folderName = file.slice(0, -baseName.length - 1);
1567
- const actualDecorationIcon = getActualDecorationIcon(iconDefinitions, icon);
1568
- displayItems.push({
1569
- file,
1570
- label: baseName,
1571
- detail: folderName,
1572
- posInSet: i + 1,
1573
- setSize: length,
1574
- icon: getFileIcon({
1575
- name: file
1576
- }),
1577
- decorationIcon: actualDecorationIcon,
1578
- decorationIconTitle: iconTitle,
1579
- decorationStrikeThrough: strikeThrough,
1580
- type: File,
1581
- badgeCount: 0,
1582
- groupId: id
1583
- });
1584
- }
1585
- }
1586
- return displayItems;
1587
- };
1588
-
1589
- const getDisplayItems = (allGroups, expandedGroups, iconDefinitions) => {
1590
- const displayItems = [];
1591
- for (const group of allGroups) {
1592
- const groupDisplayItems = getDisplayItemsGroup(group, expandedGroups, iconDefinitions);
1593
- displayItems.push(...groupDisplayItems);
1594
- }
1595
- return displayItems;
1596
- };
1597
-
1598
- const getIconType = direntType => {
1599
- switch (direntType) {
1600
- case Directory:
1601
- case DirectoryExpanded:
1602
- return 2;
1603
- default:
1604
- return 1;
1605
- }
1606
- };
1607
-
1608
- const getMissingIconRequests = (dirents, fileIconCache) => {
1609
- const missingRequests = [];
1610
- for (const dirent of dirents) {
1611
- if (!(dirent.file in fileIconCache)) {
1612
- missingRequests.push({
1613
- type: getIconType(dirent.type),
1614
- name: dirent.label
1615
- });
1616
- }
1617
- }
1618
- return missingRequests;
1619
- };
1620
-
1621
- const requestFileIcons = async requests => {
1622
- const results = await invoke('IconTheme.getIcons', requests);
1623
- return results;
1624
- };
1721
+ inputValue
1722
+ } = restoreState(savedState);
1723
+ const enabledProviderIds = await getEnabledProviderIds(scheme, root);
1724
+ const iconDefinitions = await getIconDefinitions(enabledProviderIds);
1725
+ const {
1726
+ allGroups,
1727
+ gitRoot
1728
+ } = await getGroups(enabledProviderIds);
1729
+ const expandedGroups = restoreExpandedGroups(allGroups);
1730
+ const displayItems = getDisplayItems(allGroups, expandedGroups, iconDefinitions);
1731
+ const actionsCache = await requestSourceActions();
1625
1732
 
1626
- const updateIconCache = (iconCache, missingRequests, newIcons) => {
1627
- if (missingRequests.length === 0) {
1628
- return iconCache;
1629
- }
1630
- const newFileIconCache = {
1631
- ...iconCache
1733
+ // TODO make preferences async and more functional
1734
+ const splitButtonEnabled = await get$1('sourceControl.splitButtonEnabled');
1735
+ const total = displayItems.length;
1736
+ const contentHeight = total * itemHeight;
1737
+ const listHeight = getListHeight(total, itemHeight, height);
1738
+ const scrollBarHeight = getScrollBarSize(height, contentHeight, minimumSliderSize);
1739
+ const numberOfVisible = getNumberOfVisibleItems(listHeight, itemHeight);
1740
+ const minLineY = 0;
1741
+ const maxLineY = Math.min(numberOfVisible, total);
1742
+ const newFileIconCache = await getFileIcons(displayItems, fileIconCache);
1743
+ const visibleItems = getVisibleSourceControlItems(displayItems, minLineY, maxLineY, actionsCache, newFileIconCache);
1744
+ const finalDeltaY = getFinalDeltaY(listHeight, itemHeight, total);
1745
+ const inputPlaceholder = messageEnterToCommitOnMaster();
1746
+ const inputBoxHeight = await getInputHeight(inputValue, width, inputFontFamily, inputFontSize, inputFontWeight, inputLetterSpacing, inputLineHeight);
1747
+ return {
1748
+ ...state,
1749
+ actionsCache,
1750
+ allGroups,
1751
+ decorationIcons: iconDefinitions,
1752
+ enabledProviderIds,
1753
+ fileIconCache: newFileIconCache,
1754
+ finalDeltaY,
1755
+ gitRoot,
1756
+ iconDefinitions,
1757
+ inputBoxHeight,
1758
+ inputPlaceholder,
1759
+ inputValue,
1760
+ items: displayItems,
1761
+ maxLineY,
1762
+ root,
1763
+ scrollBarHeight,
1764
+ splitButtonEnabled,
1765
+ visibleItems
1632
1766
  };
1633
- for (let i = 0; i < missingRequests.length; i++) {
1634
- const request = missingRequests[i];
1635
- const icon = newIcons[i];
1636
- newFileIconCache[request.name] = icon;
1637
- }
1638
- return newFileIconCache;
1639
1767
  };
1640
1768
 
1641
- const getFileIcons = async (dirents, fileIconCache) => {
1642
- const missingRequests = getMissingIconRequests(dirents, fileIconCache);
1643
- const newIcons = await requestFileIcons(missingRequests);
1644
- const newFileIconCache = updateIconCache(fileIconCache, missingRequests, newIcons);
1645
- return newFileIconCache;
1646
- };
1647
-
1648
- const getFinalDeltaY = (height, itemHeight, itemsLength) => {
1649
- const contentHeight = itemsLength * itemHeight;
1650
- const finalDeltaY = Math.max(contentHeight - height, 0);
1651
- return finalDeltaY;
1652
- };
1653
-
1654
- const getFileDecorations$1 = (providerId, uris) => {
1655
- return executeProvider({
1656
- event: 'none',
1657
- method: SourceControlGetFileDecorations,
1658
- params: [providerId, uris]
1659
- });
1660
- };
1661
- const getFileBefore$1 = (providerId, path) => {
1662
- return executeProvider({
1663
- event: 'none',
1664
- method: SourceControlGetFileBefore,
1665
- params: [providerId, path]
1666
- // noProviderFoundMessage: 'No source control provider found',
1667
- });
1668
- };
1669
- const getGroups$2 = (providerId, path) => {
1670
- return executeProvider({
1671
- event: 'none',
1672
- method: SourceControlGetGroups,
1673
- params: [providerId, path]
1674
- // noProviderFoundMessage: 'No source control provider found',
1675
- });
1676
- };
1677
- const getEnabledProviderIds$1 = (scheme, root) => {
1678
- return executeProvider({
1679
- event: `onSourceControl:${scheme}`,
1680
- method: SourceControlGetEnabledProviderIds,
1681
- params: [scheme, root]
1682
- // noProviderFoundMessage: 'No source control provider found',
1683
- });
1684
- };
1685
- const getIconDefinitions$1 = async providerId => {
1769
+ const info = (...args) => {
1686
1770
  // @ts-ignore
1687
- const result = await invoke$1('ExtensionHostSourceControl.getIconDefinitions', providerId);
1688
- return result;
1771
+ // eslint-disable-next-line no-console
1772
+ console.info(...args);
1689
1773
  };
1690
-
1691
- const getFileDecorations = (providerId, uris) => {
1692
- return getFileDecorations$1(providerId, uris);
1693
- };
1694
- const getFileBefore = (providerId, file) => {
1695
- return getFileBefore$1(providerId, file);
1696
- };
1697
- const getEnabledProviderIds = (scheme, root) => {
1698
- string(scheme);
1699
- string(root);
1700
- return getEnabledProviderIds$1(scheme, root);
1701
- };
1702
- const getGroups$1 = (providerId, root) => {
1703
- return getGroups$2(providerId, root);
1704
- };
1705
- const getIconDefinitions = async providerIds => {
1706
- try {
1707
- if (providerIds.length === 0) {
1708
- return [];
1709
- }
1710
- return await getIconDefinitions$1(providerIds[0]);
1711
- } catch {
1712
- return [];
1713
- }
1774
+ const warn = (...args) => {
1775
+ // @ts-ignore
1776
+ console.warn(...args);
1714
1777
  };
1715
1778
 
1716
- const getGroups = async enabledProviderIds => {
1717
- const allGroups = [];
1718
- for (const providerId of enabledProviderIds) {
1719
- // @ts-ignore
1720
- const groups = await getGroups$1(providerId);
1721
- allGroups.push(...groups);
1779
+ const acceptInput = async state => {
1780
+ const {
1781
+ inputValue,
1782
+ enabledProviderIds
1783
+ } = state;
1784
+ if (enabledProviderIds.length === 0) {
1785
+ info('[ViewletSourceControl] no source control provider found');
1786
+ return state;
1722
1787
  }
1788
+ const providerId = enabledProviderIds[0];
1789
+ await acceptInput$1(providerId, inputValue);
1790
+ const newState = await loadContent(state, {});
1723
1791
  return {
1724
- allGroups,
1725
- gitRoot: ''
1792
+ ...newState,
1793
+ inputValue: ''
1726
1794
  };
1727
1795
  };
1728
1796
 
1729
- const getTextHeight = async (input, width, fontFamily, fontSize, fontWeight, letterSpacing, lineHeight) => {
1730
- try {
1731
- if (!input) {
1732
- return lineHeight;
1733
- }
1734
- const actualInput = input;
1735
- // TODO line height could also be like 1.5
1736
- const lineHeightPx = `${lineHeight}px`;
1737
- // @ts-ignore
1738
- const height = await invoke(`MeasureTextHeight.measureTextBlockHeight`, actualInput, fontFamily, fontSize, lineHeightPx, width);
1739
- return height;
1740
- } catch {
1741
- // fallback
1742
- const lines = input.split('\n');
1743
- const lineCount = lines.length;
1744
- const inputHeight = lineCount * lineHeight;
1745
- return inputHeight;
1746
- }
1747
- };
1797
+ const {
1798
+ get,
1799
+ set,
1800
+ wrapCommand,
1801
+ getCommandIds,
1802
+ registerCommands,
1803
+ wrapGetter
1804
+ } = create();
1748
1805
 
1749
- const getInputHeight = async (input, width, fontFamily, fontWeight, fontSize, letterSpacing, lineHeight) => {
1750
- const height = await getTextHeight(input, width, fontFamily, fontSize, fontWeight, letterSpacing, lineHeight);
1751
- return height;
1806
+ const create2 = (id, uri, x, y, width, height, workspacePath) => {
1807
+ const state = {
1808
+ actionsCache: Object.create(null),
1809
+ allGroups: [],
1810
+ deltaY: 0,
1811
+ enabledProviderIds: [],
1812
+ fileIconCache: Object.create(null),
1813
+ finalDeltaY: 0,
1814
+ gitRoot: '',
1815
+ handleOffset: 0,
1816
+ headerHeight: 40,
1817
+ // TODO
1818
+ height,
1819
+ id,
1820
+ index: [],
1821
+ inputValue: '',
1822
+ expandedGroups: Object.create(null),
1823
+ itemHeight: 20,
1824
+ items: [],
1825
+ maxLineY: 0,
1826
+ merge: [],
1827
+ minimumSliderSize: 20,
1828
+ inputBoxHeight: 30,
1829
+ minLineY: 0,
1830
+ providerId: '',
1831
+ root: '',
1832
+ scrollBarActive: false,
1833
+ scrollBarHeight: 0,
1834
+ splitButtonEnabled: false,
1835
+ untracked: [],
1836
+ visibleItems: [],
1837
+ width,
1838
+ workingTree: [],
1839
+ workspacePath,
1840
+ x,
1841
+ y,
1842
+ inputPlaceholder: '',
1843
+ inputSource: 0,
1844
+ maxInputLines: 5,
1845
+ inputFontFamily: 'system-ui, Ubuntu, "Droid Sans", sans-serif',
1846
+ inputFontSize: 13,
1847
+ inputFontWeight: 400,
1848
+ inputLetterSpacing: 0,
1849
+ inputLineHeight: 20,
1850
+ inputBoxMaxHeight: 214,
1851
+ history: [],
1852
+ viewMode: 1,
1853
+ iconDefinitions: [],
1854
+ decorationIcons: [],
1855
+ focus: 0,
1856
+ isVisible: true,
1857
+ badgeCount: 0
1858
+ };
1859
+ set(id, state, state);
1752
1860
  };
1753
1861
 
1754
- const getListHeight = (itemsLength, itemHeight, maxHeight) => {
1755
- number(itemsLength);
1756
- number(itemHeight);
1757
- number(maxHeight);
1758
- if (itemsLength === 0) {
1759
- return itemHeight;
1760
- }
1761
- const totalHeight = itemsLength * itemHeight;
1762
- return Math.min(totalHeight, maxHeight);
1862
+ const isEqual$3 = (oldState, newState) => {
1863
+ return oldState.inputBoxHeight === newState.inputBoxHeight;
1763
1864
  };
1764
1865
 
1765
- // TODO optimize this function to return the minimum number
1766
- // of visible items needed, e.g. when not scrolled 5 items with
1767
- // 20px fill 100px but when scrolled 6 items are needed
1768
- const getNumberOfVisibleItems = (listHeight, itemHeight) => {
1769
- return Math.ceil(listHeight / itemHeight) + 1;
1866
+ const isEqual$2 = (oldState, newState) => {
1867
+ return oldState.focus === newState.focus;
1770
1868
  };
1771
1869
 
1772
- const Disk = 'file';
1773
-
1774
- const RE_PROTOCOL = /^([a-z-]+):\/\//;
1775
- const getProtocol = uri => {
1776
- if (!uri) {
1777
- return Disk;
1778
- }
1779
- const protocolMatch = uri.match(RE_PROTOCOL);
1780
- if (protocolMatch) {
1781
- return protocolMatch[1];
1782
- }
1783
- return Disk;
1870
+ const isEqual$1 = (oldState, newState) => {
1871
+ return oldState.allGroups === newState.allGroups && oldState.deltaY === newState.deltaY && oldState.items === newState.items && oldState.maxLineY === newState.maxLineY && oldState.minLineY === newState.minLineY && oldState.visibleItems === newState.visibleItems;
1784
1872
  };
1785
1873
 
1786
- const emptySourceControlButtons = [];
1787
-
1788
- const getContextId = (groupId, type) => {
1789
- if (type === File) {
1790
- return `${groupId}-item`;
1791
- }
1792
- return groupId;
1793
- };
1874
+ const RenderItems = 4;
1875
+ const RenderFocusContext = 7;
1876
+ const RenderValue = 8;
1877
+ const RenderCss = 10;
1794
1878
 
1795
- const getVisibleSourceControlItems = (items, minLineY, maxLineY, actionsCache, fileIconCache) => {
1796
- const visible = [];
1797
- for (let i = minLineY; i < maxLineY; i++) {
1798
- const item = items[i];
1799
- const contextId = getContextId(item.groupId, item.type);
1800
- const buttons = actionsCache[contextId] || emptySourceControlButtons;
1801
- const fileIcon = fileIconCache[item.label] || '';
1802
- visible.push({
1803
- ...item,
1804
- buttons,
1805
- fileIcon
1806
- });
1807
- }
1808
- return visible;
1879
+ const isEqual = (oldState, newState) => {
1880
+ return newState.inputSource === User || oldState.inputValue === newState.inputValue;
1809
1881
  };
1810
1882
 
1811
- const get = key => {
1812
- return getPreference(key);
1883
+ const modules = [isEqual$1, isEqual, isEqual$3, isEqual$2];
1884
+ const numbers = [RenderItems, RenderValue, RenderCss, RenderFocusContext];
1885
+
1886
+ const diff = (oldState, newState) => {
1887
+ const diffResult = [];
1888
+ for (let i = 0; i < modules.length; i++) {
1889
+ const fn = modules[i];
1890
+ if (!fn(oldState, newState)) {
1891
+ diffResult.push(numbers[i]);
1892
+ }
1893
+ }
1894
+ return diffResult;
1813
1895
  };
1814
1896
 
1815
- const getExtensions = async () => {
1816
- return invoke$1('Extensions.getExtensions');
1897
+ const diff2 = uid => {
1898
+ const {
1899
+ oldState,
1900
+ newState
1901
+ } = get(uid);
1902
+ const result = diff(oldState, newState);
1903
+ return result;
1817
1904
  };
1818
1905
 
1819
- const requestSourceActions = async () => {
1820
- const extensions = await getExtensions();
1821
- const newCache = Object.create(null);
1822
- for (const extension of extensions) {
1823
- if (extension && extension['source-control-actions']) {
1824
- for (const [key, value] of Object.entries(extension['source-control-actions'])) {
1825
- newCache[key] = value;
1826
- }
1827
- }
1828
- }
1829
- return newCache;
1906
+ const getBadgeCount = state => {
1907
+ return state.badgeCount;
1830
1908
  };
1831
1909
 
1832
- /* eslint-disable unicorn/no-array-reduce */
1833
- const restoreExpandedGroups = groups => {
1834
- return groups.map(group => group.id).reduce((total, current) => {
1835
- return {
1836
- ...total,
1837
- [current]: true
1838
- };
1839
- }, Object.create(null));
1910
+ const getInfo = uid => {
1911
+ const {
1912
+ newState
1913
+ } = get(uid);
1914
+ return newState.allGroups;
1840
1915
  };
1841
1916
 
1842
- const getRestoredInputValue = savedState => {
1843
- if (savedState && typeof savedState === 'object' && 'inputValue' in savedState && typeof savedState['inputValue'] === 'string') {
1844
- return savedState.inputValue;
1845
- }
1846
- return '';
1917
+ const mergeClassNames = (...classNames) => {
1918
+ return classNames.filter(Boolean).join(' ');
1847
1919
  };
1848
- const restoreState = savedState => {
1849
- const inputValue = getRestoredInputValue(savedState);
1920
+
1921
+ const text = data => {
1850
1922
  return {
1851
- inputValue
1923
+ type: Text,
1924
+ text: data,
1925
+ childCount: 0
1852
1926
  };
1853
1927
  };
1854
1928
 
1855
- const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
1856
- if (size >= contentSize) {
1857
- return 0;
1858
- }
1859
- return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
1929
+ const getKeyBindings = () => {
1930
+ return [{
1931
+ key: CtrlCmd | Enter,
1932
+ command: 'Source Control.acceptInput',
1933
+ when: FocusSourceControlInput
1934
+ }];
1860
1935
  };
1861
1936
 
1862
- const loadContent = async (state, savedState) => {
1937
+ const getMenuEntries = () => {
1938
+ return [{
1939
+ label: openChanges(),
1940
+ flags: None,
1941
+ command: /* TODO */'-1',
1942
+ id: ''
1943
+ }, {
1944
+ label: openFile(),
1945
+ flags: None,
1946
+ command: /* TODO */'-1',
1947
+ id: ''
1948
+ }, {
1949
+ label: openFileHead(),
1950
+ flags: None,
1951
+ command: /* TODO */'-1',
1952
+ id: ''
1953
+ }, {
1954
+ label: discardChanges(),
1955
+ flags: None,
1956
+ command: /* TODO */'-1',
1957
+ id: ''
1958
+ }, {
1959
+ label: stageChanges(),
1960
+ flags: None,
1961
+ command: /* TODO */'-1',
1962
+ id: ''
1963
+ }, {
1964
+ label: addToGitignore(),
1965
+ flags: None,
1966
+ command: /* TODO */'-1',
1967
+ id: ''
1968
+ }, {
1969
+ label: revealInExplorerView(),
1970
+ flags: None,
1971
+ command: /* TODO */'-1',
1972
+ id: ''
1973
+ }, {
1974
+ label: openContainingFolder(),
1975
+ flags: None,
1976
+ command: /* TODO */'-1',
1977
+ id: ''
1978
+ }];
1979
+ };
1980
+
1981
+ const getMenuEntries2 = state => {
1982
+ return getMenuEntries();
1983
+ };
1984
+
1985
+ const getMenuIds = () => {
1986
+ return [SourceControl$1];
1987
+ };
1988
+
1989
+ const SourceControlInput = 'SourceControlInput';
1990
+ const ViewAsTree = 'ViewAsTree';
1991
+ const CommitAndPush = 'CommitAndPush';
1992
+ const Refresh$1 = 'Refresh';
1993
+
1994
+ const refresh = async state => {
1863
1995
  const {
1864
1996
  itemHeight,
1865
1997
  height,
1866
1998
  minimumSliderSize,
1867
- workspacePath,
1868
1999
  fileIconCache,
1869
- width,
1870
- inputFontFamily,
1871
- inputFontSize,
1872
- inputFontWeight,
1873
- inputLetterSpacing,
1874
- inputLineHeight
2000
+ enabledProviderIds,
2001
+ splitButtonEnabled,
2002
+ actionsCache,
2003
+ iconDefinitions
1875
2004
  } = state;
1876
- const root = workspacePath;
1877
- const scheme = getProtocol(root);
1878
- const {
1879
- inputValue
1880
- } = restoreState(savedState);
1881
- const enabledProviderIds = await getEnabledProviderIds(scheme, root);
1882
- const iconDefinitions = await getIconDefinitions(enabledProviderIds);
1883
2005
  const {
1884
2006
  allGroups,
1885
2007
  gitRoot
1886
2008
  } = await getGroups(enabledProviderIds);
1887
2009
  const expandedGroups = restoreExpandedGroups(allGroups);
1888
2010
  const displayItems = getDisplayItems(allGroups, expandedGroups, iconDefinitions);
1889
- const actionsCache = await requestSourceActions();
1890
-
1891
- // TODO make preferences async and more functional
1892
- const splitButtonEnabled = await get('sourceControl.splitButtonEnabled');
1893
2011
  const total = displayItems.length;
1894
2012
  const contentHeight = total * itemHeight;
1895
2013
  const listHeight = getListHeight(total, itemHeight, height);
@@ -1900,30 +2018,52 @@ const loadContent = async (state, savedState) => {
1900
2018
  const newFileIconCache = await getFileIcons(displayItems, fileIconCache);
1901
2019
  const visibleItems = getVisibleSourceControlItems(displayItems, minLineY, maxLineY, actionsCache, newFileIconCache);
1902
2020
  const finalDeltaY = getFinalDeltaY(listHeight, itemHeight, total);
1903
- const inputPlaceholder = messageEnterToCommitOnMaster();
1904
- const inputBoxHeight = await getInputHeight(inputValue, width, inputFontFamily, inputFontSize, inputFontWeight, inputLetterSpacing, inputLineHeight);
1905
2021
  return {
1906
2022
  ...state,
1907
2023
  actionsCache,
1908
2024
  allGroups,
1909
- decorationIcons: iconDefinitions,
1910
2025
  enabledProviderIds,
1911
2026
  fileIconCache: newFileIconCache,
1912
2027
  finalDeltaY,
1913
2028
  gitRoot,
1914
- iconDefinitions,
1915
- inputBoxHeight,
1916
- inputPlaceholder,
1917
- inputValue,
1918
2029
  items: displayItems,
1919
2030
  maxLineY,
1920
- root,
1921
2031
  scrollBarHeight,
1922
2032
  splitButtonEnabled,
1923
2033
  visibleItems
1924
2034
  };
1925
2035
  };
1926
2036
 
2037
+ const viewAsTree = state => {
2038
+ return {
2039
+ ...state,
2040
+ viewMode: Tree
2041
+ };
2042
+ };
2043
+
2044
+ const handleActionClick = async (state, actionName) => {
2045
+ switch (actionName) {
2046
+ case Refresh$1:
2047
+ return refresh(state);
2048
+ case ViewAsTree:
2049
+ return viewAsTree(state);
2050
+ case CommitAndPush:
2051
+ warn(`[source-control-worker] CommitAndPush action not yet implemented`);
2052
+ return state;
2053
+ default:
2054
+ warn(`[source-control-worker] Unknown action name: ${actionName}`);
2055
+ return state;
2056
+ }
2057
+ };
2058
+
2059
+ const executeCommand = (id, ...args) => {
2060
+ return executeProvider({
2061
+ event: `onCommand:${id}`,
2062
+ method: CommandExecute,
2063
+ params: [id, ...args]
2064
+ });
2065
+ };
2066
+
1927
2067
  const handleButtonClick = async (state, clickedIndex) => {
1928
2068
  const {
1929
2069
  visibleItems
@@ -1949,54 +2089,6 @@ const getIndex = (state, eventX, eventY) => {
1949
2089
  return index;
1950
2090
  };
1951
2091
 
1952
- const warn = (...args) => {
1953
- // @ts-ignore
1954
- console.warn(...args);
1955
- };
1956
-
1957
- const refresh = async state => {
1958
- const {
1959
- itemHeight,
1960
- height,
1961
- minimumSliderSize,
1962
- fileIconCache,
1963
- enabledProviderIds,
1964
- splitButtonEnabled,
1965
- actionsCache,
1966
- iconDefinitions
1967
- } = state;
1968
- const {
1969
- allGroups,
1970
- gitRoot
1971
- } = await getGroups(enabledProviderIds);
1972
- const expandedGroups = restoreExpandedGroups(allGroups);
1973
- const displayItems = getDisplayItems(allGroups, expandedGroups, iconDefinitions);
1974
- const total = displayItems.length;
1975
- const contentHeight = total * itemHeight;
1976
- const listHeight = getListHeight(total, itemHeight, height);
1977
- const scrollBarHeight = getScrollBarSize(height, contentHeight, minimumSliderSize);
1978
- const numberOfVisible = getNumberOfVisibleItems(listHeight, itemHeight);
1979
- const minLineY = 0;
1980
- const maxLineY = Math.min(numberOfVisible, total);
1981
- const newFileIconCache = await getFileIcons(displayItems, fileIconCache);
1982
- const visibleItems = getVisibleSourceControlItems(displayItems, minLineY, maxLineY, actionsCache, newFileIconCache);
1983
- const finalDeltaY = getFinalDeltaY(listHeight, itemHeight, total);
1984
- return {
1985
- ...state,
1986
- actionsCache,
1987
- allGroups,
1988
- enabledProviderIds,
1989
- fileIconCache: newFileIconCache,
1990
- finalDeltaY,
1991
- gitRoot,
1992
- items: displayItems,
1993
- maxLineY,
1994
- scrollBarHeight,
1995
- splitButtonEnabled,
1996
- visibleItems
1997
- };
1998
- };
1999
-
2000
2092
  const handleClickSourceControlButtons = async (state, index, name) => {
2001
2093
  const {
2002
2094
  visibleItems
@@ -2288,12 +2380,35 @@ const initialize = async () => {
2288
2380
  set$1(textRpc);
2289
2381
  };
2290
2382
 
2383
+ const getUnique = items => {
2384
+ const seens = [];
2385
+ for (const item of items) {
2386
+ if (!seens.includes(item)) {
2387
+ seens.push(item);
2388
+ }
2389
+ }
2390
+ return seens;
2391
+ };
2392
+
2393
+ const getIndentRule = indent => {
2394
+ return `.Indent-${indent} {
2395
+ padding-left: ${indent}px;
2396
+ }`;
2397
+ };
2291
2398
  const renderCss = (oldState, newState) => {
2292
2399
  const {
2293
2400
  id,
2294
- inputBoxHeight
2401
+ inputBoxHeight,
2402
+ visibleItems
2295
2403
  } = newState;
2296
- const css = `:root {
2404
+ const indents = visibleItems.map(item => item.indent);
2405
+ const uniqueIndents = getUnique(indents);
2406
+ const indentRules = uniqueIndents.map(getIndentRule).join('\n');
2407
+ const css = indentRules ? `:root {
2408
+ --SourceControlInputHeight: ${inputBoxHeight}px;
2409
+ }
2410
+ ${indentRules}
2411
+ ` : `:root {
2297
2412
  --SourceControlInputHeight: ${inputBoxHeight}px;
2298
2413
  }
2299
2414
  `;
@@ -2345,8 +2460,6 @@ const HandleMouseOver = 7;
2345
2460
  const HandleMouseOverAt = 8;
2346
2461
  const HandleWheel = 9;
2347
2462
 
2348
- const SourceControlInput = 'SourceControlInput';
2349
-
2350
2463
  const getSourceControlInputDom = inputPlaceholder => {
2351
2464
  return [{
2352
2465
  type: TextArea,
@@ -2425,7 +2538,12 @@ const getLabelClassName = decorationStrikeThrough => {
2425
2538
  return classNameDefault;
2426
2539
  };
2427
2540
 
2428
- const PaddingLeft = '1rem';
2541
+ const getTreeItemClassName = indent => {
2542
+ let className = TreeItem;
2543
+ className = mergeClassNames(className, `Indent-${indent}`);
2544
+ return className;
2545
+ };
2546
+
2429
2547
  const PaddingRight = '12px';
2430
2548
 
2431
2549
  const createItemDirectory = item => {
@@ -2437,21 +2555,21 @@ const createItemDirectory = item => {
2437
2555
  badgeCount,
2438
2556
  decorationStrikeThrough,
2439
2557
  type,
2440
- buttons
2558
+ buttons,
2559
+ indent
2441
2560
  } = item;
2442
2561
  const labelClassName = getLabelClassName(decorationStrikeThrough);
2443
2562
  const buttonsDom = getButtonsVirtualDom(buttons);
2444
2563
  const hasButtons = buttons.length;
2564
+ const treeItemClassName = getTreeItemClassName(indent);
2445
2565
  return [{
2446
2566
  type: Div,
2447
- className: TreeItem,
2567
+ className: treeItemClassName,
2448
2568
  role: TreeItem$1,
2449
2569
  ariaExpanded: type === DirectoryExpanded,
2450
2570
  ariaPosInSet: posInSet,
2451
2571
  ariaSetSize: setSize,
2452
2572
  childCount: 3 + (hasButtons ? 1 : 0),
2453
- paddingLeft: PaddingLeft,
2454
- // TODO classname for indent / padding
2455
2573
  paddingRight: PaddingRight
2456
2574
  }, {
2457
2575
  type: Div,
@@ -2497,21 +2615,22 @@ const createItemOther = item => {
2497
2615
  decorationStrikeThrough,
2498
2616
  detail,
2499
2617
  buttons,
2500
- fileIcon
2618
+ fileIcon,
2619
+ indent
2501
2620
  } = item;
2502
2621
  const labelClassName = getLabelClassName(decorationStrikeThrough);
2503
2622
  const dom = [];
2504
2623
  const hasButtons = buttons.length;
2505
2624
  const buttonsDom = getButtonsVirtualDom(buttons);
2625
+ const treeItemClassName = getTreeItemClassName(indent);
2506
2626
  dom.push({
2507
2627
  type: Div,
2508
- className: TreeItem,
2628
+ className: treeItemClassName,
2509
2629
  role: TreeItem$1,
2510
2630
  ariaPosInSet: posInSet,
2511
2631
  ariaSetSize: setSize,
2512
2632
  title: file,
2513
2633
  childCount: 3 + (hasButtons ? 1 : 0),
2514
- paddingLeft: '1rem',
2515
2634
  paddingRight: '12px'
2516
2635
  }, ...getIconsDom(icon, fileIcon));
2517
2636
  const labelDom = {
@@ -2656,7 +2775,7 @@ const render2 = (uid, diffResult) => {
2656
2775
  const {
2657
2776
  oldState,
2658
2777
  newState
2659
- } = get$1(uid);
2778
+ } = get(uid);
2660
2779
  set(uid, newState, newState);
2661
2780
  const commands = applyRender(oldState, newState, diffResult);
2662
2781
  return commands;
@@ -2664,18 +2783,43 @@ const render2 = (uid, diffResult) => {
2664
2783
 
2665
2784
  const Button = 1;
2666
2785
 
2786
+ const Check = 'Check';
2787
+ const ListFlat = 'ListFlat';
2788
+ const Refresh = 'Refresh';
2789
+
2790
+ const getActions = () => {
2791
+ return [{
2792
+ type: Button,
2793
+ id: viewAsTree$1(),
2794
+ name: ViewAsTree,
2795
+ icon: ListFlat,
2796
+ command: ''
2797
+ }, {
2798
+ type: Button,
2799
+ id: commitAndPush(),
2800
+ name: CommitAndPush,
2801
+ icon: Check,
2802
+ command: ''
2803
+ }, {
2804
+ type: Button,
2805
+ id: refresh$1(),
2806
+ name: Refresh$1,
2807
+ icon: Refresh,
2808
+ command: ''
2809
+ }];
2810
+ };
2811
+
2667
2812
  const getActionButtonVirtualDom = action => {
2668
2813
  const {
2669
2814
  id,
2670
2815
  icon,
2671
- command
2816
+ label
2672
2817
  } = action;
2673
2818
  return [{
2674
2819
  type: Button$2,
2675
2820
  className: IconButton,
2676
2821
  title: id,
2677
- 'data-command': command,
2678
- // TODO remove this
2822
+ name: label,
2679
2823
  childCount: 1
2680
2824
  }, getIconVirtualDom(icon)];
2681
2825
  };
@@ -2683,7 +2827,14 @@ const getActionButtonVirtualDom = action => {
2683
2827
  const getActionVirtualDom = action => {
2684
2828
  switch (action.type) {
2685
2829
  case Button:
2686
- return getActionButtonVirtualDom(action);
2830
+ {
2831
+ const actionButton = {
2832
+ id: action.id,
2833
+ icon: action.icon,
2834
+ label: action.name
2835
+ };
2836
+ return getActionButtonVirtualDom(actionButton);
2837
+ }
2687
2838
  default:
2688
2839
  return [];
2689
2840
  }
@@ -2699,7 +2850,7 @@ const getActionsVirtualDom = actions => {
2699
2850
  };
2700
2851
 
2701
2852
  const renderActions = state => {
2702
- const actions = [];
2853
+ const actions = getActions();
2703
2854
  const dom = getActionsVirtualDom(actions);
2704
2855
  return dom;
2705
2856
  };
@@ -2740,7 +2891,7 @@ const renderEventListeners = () => {
2740
2891
 
2741
2892
  const saveState = uid => {
2742
2893
  number(uid);
2743
- const value = get$1(uid);
2894
+ const value = get(uid);
2744
2895
  const {
2745
2896
  newState
2746
2897
  } = value;
@@ -2782,17 +2933,12 @@ const viewAsList = state => {
2782
2933
  };
2783
2934
  };
2784
2935
 
2785
- const viewAsTree = state => {
2786
- return {
2787
- ...state,
2788
- viewMode: Tree
2789
- };
2790
- };
2791
-
2792
2936
  const commandMap = {
2793
2937
  'Initialize.initialize': initialize,
2938
+ 'SourceControl.acceptInput': wrapCommand(acceptInput),
2794
2939
  'SourceControl.create2': create2,
2795
2940
  'SourceControl.diff2': diff2,
2941
+ 'SourceControl.getBadgeCount': wrapGetter(getBadgeCount),
2796
2942
  'SourceControl.getCommandIds': getCommandIds,
2797
2943
  'SourceControl.getEnabledProviderIds': getEnabledProviderIds,
2798
2944
  'SourceControl.getFileDecorations': getFileDecorations,
@@ -2800,12 +2946,14 @@ const commandMap = {
2800
2946
  'SourceControl.getKeyBindings': getKeyBindings,
2801
2947
  'SourceControl.getMenuEntries2': wrapGetter(getMenuEntries2),
2802
2948
  'SourceControl.getMenuIds': getMenuIds,
2949
+ 'SourceControl.handleActionClick': wrapCommand(handleActionClick),
2803
2950
  'SourceControl.handleButtonClick': wrapCommand(handleButtonClick),
2804
2951
  'SourceControl.handleClickAt': wrapCommand(handleClickAt),
2805
2952
  'SourceControl.handleClickSourceControlButtons': wrapCommand(handleClickSourceControlButtons),
2806
2953
  'SourceControl.handleContextMenu': wrapCommand(handleContextMenu),
2807
2954
  'SourceControl.handleFocus': wrapCommand(handleInputFocus),
2808
2955
  'SourceControl.handleInput': wrapCommand(handleInput),
2956
+ 'SourceControl.handleInputBlur': wrapCommand(handleInputBlur),
2809
2957
  'SourceControl.handleMessagePort': handleMessagePort,
2810
2958
  'SourceControl.handleMouseOut': wrapCommand(handleMouseOut),
2811
2959
  'SourceControl.handleMouseOutAt': wrapCommand(handleMouseOutAt),
@@ -2825,8 +2973,7 @@ const commandMap = {
2825
2973
  'SourceControl.terminate': terminate,
2826
2974
  'SourceControl.updateIcons': wrapCommand(updateIcons),
2827
2975
  'SourceControl.viewAsList': wrapCommand(viewAsList),
2828
- 'SourceControl.viewAsTree': wrapCommand(viewAsTree),
2829
- 'SourceControl.handleInputBlur': wrapCommand(handleInputBlur)
2976
+ 'SourceControl.viewAsTree': wrapCommand(viewAsTree)
2830
2977
  };
2831
2978
 
2832
2979
  const listen = async () => {