@codingame/monaco-vscode-scm-service-override 22.1.8 → 23.0.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.
Files changed (27) hide show
  1. package/package.json +13 -15
  2. package/vscode/src/vs/workbench/contrib/scm/browser/activity.js +31 -45
  3. package/vscode/src/vs/workbench/contrib/scm/browser/media/dirtydiffDecorator.css +6 -6
  4. package/vscode/src/vs/workbench/contrib/scm/browser/media/scm.css +103 -18
  5. package/vscode/src/vs/workbench/contrib/scm/browser/menus.d.ts +7 -4
  6. package/vscode/src/vs/workbench/contrib/scm/browser/menus.js +39 -12
  7. package/vscode/src/vs/workbench/contrib/scm/browser/quickDiffDecorator.js +10 -10
  8. package/vscode/src/vs/workbench/contrib/scm/browser/quickDiffModel.d.ts +1 -1
  9. package/vscode/src/vs/workbench/contrib/scm/browser/quickDiffModel.js +5 -5
  10. package/vscode/src/vs/workbench/contrib/scm/browser/quickDiffWidget.d.ts +1 -1
  11. package/vscode/src/vs/workbench/contrib/scm/browser/quickDiffWidget.js +14 -14
  12. package/vscode/src/vs/workbench/contrib/scm/browser/scm.contribution.js +126 -89
  13. package/vscode/src/vs/workbench/contrib/scm/browser/scmAccessibilityHelp.js +24 -24
  14. package/vscode/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.d.ts +7 -2
  15. package/vscode/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.js +180 -115
  16. package/vscode/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.d.ts +5 -0
  17. package/vscode/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.js +457 -79
  18. package/vscode/src/vs/workbench/contrib/scm/browser/scmRepositoryRenderer.d.ts +8 -2
  19. package/vscode/src/vs/workbench/contrib/scm/browser/scmRepositoryRenderer.js +66 -20
  20. package/vscode/src/vs/workbench/contrib/scm/browser/scmViewPane.d.ts +3 -2
  21. package/vscode/src/vs/workbench/contrib/scm/browser/scmViewPane.js +93 -74
  22. package/vscode/src/vs/workbench/contrib/scm/browser/scmViewPaneContainer.js +1 -1
  23. package/vscode/src/vs/workbench/contrib/scm/browser/scmViewService.d.ts +15 -5
  24. package/vscode/src/vs/workbench/contrib/scm/browser/scmViewService.js +88 -32
  25. package/vscode/src/vs/workbench/contrib/scm/browser/workingSet.js +5 -5
  26. package/vscode/src/vs/workbench/contrib/scm/common/scmService.d.ts +1 -1
  27. package/vscode/src/vs/workbench/contrib/scm/common/scmService.js +1 -1
@@ -12,52 +12,304 @@ import { IContextMenuService } from '@codingame/monaco-vscode-api/vscode/vs/plat
12
12
  import { IContextKeyService } from '@codingame/monaco-vscode-api/vscode/vs/platform/contextkey/common/contextkey.service';
13
13
  import { IKeybindingService } from '@codingame/monaco-vscode-api/vscode/vs/platform/keybinding/common/keybinding.service';
14
14
  import { IThemeService } from '@codingame/monaco-vscode-api/vscode/vs/platform/theme/common/themeService.service';
15
- import { Disposable, DisposableStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
15
+ import { combinedDisposable, DisposableStore, Disposable, DisposableMap } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
16
16
  import { IConfigurationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service';
17
17
  import { IViewDescriptorService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/common/views.service';
18
18
  import { IOpenerService } from '@codingame/monaco-vscode-api/vscode/vs/platform/opener/common/opener.service';
19
19
  import { RepositoryRenderer, RepositoryActionRunner } from './scmRepositoryRenderer.js';
20
- import { isSCMRepository, getActionViewItemProvider, collectContextMenuActions } from '@codingame/monaco-vscode-5084de40-f866-5cb5-9d9b-33a10f6f235d-common/vscode/vs/workbench/contrib/scm/browser/util';
20
+ import { isSCMRepository, isSCMArtifactGroupTreeElement, isSCMArtifactTreeElement, isSCMArtifactNode, connectPrimaryMenu, getActionViewItemProvider, collectContextMenuActions } from '@codingame/monaco-vscode-bc6f260d-ec63-5c95-9446-1ca7d0872719-common/vscode/vs/workbench/contrib/scm/browser/util';
21
21
  import { Orientation } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/sash/sash';
22
22
  import { Iterable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/iterator';
23
23
  import { MenuId } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/common/actions';
24
+ import { IMenuService } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/common/actions.service';
24
25
  import { IHoverService } from '@codingame/monaco-vscode-api/vscode/vs/platform/hover/browser/hover.service';
25
26
  import { observableConfigValue } from '@codingame/monaco-vscode-api/vscode/vs/platform/observable/common/platformObservableUtils';
26
27
  import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
27
- import { Sequencer } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
28
+ import { Sequencer, Throttler } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
29
+ import { IconLabel } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/iconLabel/iconLabel';
30
+ import { SCMViewService } from './scmViewService.js';
31
+ import { ThemeIcon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/themables';
32
+ import { WorkbenchToolBar } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/browser/toolbar';
33
+ import { ITelemetryService } from '@codingame/monaco-vscode-api/vscode/vs/platform/telemetry/common/telemetry.service';
34
+ import { ICommandService } from '@codingame/monaco-vscode-api/vscode/vs/platform/commands/common/commands.service';
35
+ import { ResourceTree } from '@codingame/monaco-vscode-bc6f260d-ec63-5c95-9446-1ca7d0872719-common/vscode/vs/base/common/resourceTree';
36
+ import { URI } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uri';
37
+ import { basename } from '@codingame/monaco-vscode-api/vscode/vs/base/common/resources';
38
+ import { Codicon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/codicons';
28
39
  import { autorun } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/reactions/autorun';
29
- import { observableFromEvent } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableFromEvent';
40
+ import { runOnChange } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/utils/runOnChange';
30
41
  import { observableSignalFromEvent } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableSignalFromEvent';
31
42
 
43
+ var ArtifactGroupRenderer_1, ArtifactRenderer_1;
32
44
  registerCss(scm);
33
45
  class ListDelegate {
34
46
  getHeight() {
35
47
  return 22;
36
48
  }
37
- getTemplateId() {
38
- return RepositoryRenderer.TEMPLATE_ID;
49
+ getTemplateId(element) {
50
+ if (isSCMRepository(element)) {
51
+ return RepositoryRenderer.TEMPLATE_ID;
52
+ }
53
+ else if (isSCMArtifactGroupTreeElement(element)) {
54
+ return ArtifactGroupRenderer.TEMPLATE_ID;
55
+ }
56
+ else if (isSCMArtifactTreeElement(element) || isSCMArtifactNode(element)) {
57
+ return ArtifactRenderer.TEMPLATE_ID;
58
+ }
59
+ else {
60
+ throw ( new Error('Invalid tree element'));
61
+ }
39
62
  }
40
63
  }
64
+ let ArtifactGroupRenderer = class ArtifactGroupRenderer {
65
+ static { ArtifactGroupRenderer_1 = this; }
66
+ static { this.TEMPLATE_ID = 'artifactGroup'; }
67
+ get templateId() { return ArtifactGroupRenderer_1.TEMPLATE_ID; }
68
+ constructor(_contextMenuService, _contextKeyService, _keybindingService, _menuService, _commandService, _scmViewService, _telemetryService) {
69
+ this._contextMenuService = _contextMenuService;
70
+ this._contextKeyService = _contextKeyService;
71
+ this._keybindingService = _keybindingService;
72
+ this._menuService = _menuService;
73
+ this._commandService = _commandService;
74
+ this._scmViewService = _scmViewService;
75
+ this._telemetryService = _telemetryService;
76
+ }
77
+ renderTemplate(container) {
78
+ const element = append(container, $('.scm-artifact-group'));
79
+ const icon = append(element, $('.icon'));
80
+ const label = ( new IconLabel(element, { supportIcons: false }));
81
+ const actionsContainer = append(element, $('.actions'));
82
+ const actionBar = ( new WorkbenchToolBar(
83
+ actionsContainer,
84
+ undefined,
85
+ this._menuService,
86
+ this._contextKeyService,
87
+ this._contextMenuService,
88
+ this._keybindingService,
89
+ this._commandService,
90
+ this._telemetryService
91
+ ));
92
+ return { icon, label, actionBar, elementDisposables: ( new DisposableStore()), templateDisposable: combinedDisposable(label, actionBar) };
93
+ }
94
+ renderElement(node, index, templateData) {
95
+ const provider = node.element.repository.provider;
96
+ const artifactGroup = node.element.artifactGroup;
97
+ templateData.icon.className = ThemeIcon.isThemeIcon(artifactGroup.icon)
98
+ ? `icon ${ThemeIcon.asClassName(artifactGroup.icon)}`
99
+ : '';
100
+ templateData.label.setLabel(artifactGroup.name);
101
+ const repositoryMenus = this._scmViewService.menus.getRepositoryMenus(provider);
102
+ templateData.elementDisposables.add(connectPrimaryMenu(repositoryMenus.getArtifactGroupMenu(artifactGroup), primary => {
103
+ templateData.actionBar.setActions(primary);
104
+ }, 'inline', provider));
105
+ templateData.actionBar.context = artifactGroup;
106
+ }
107
+ renderCompressedElements(node, index, templateData, details) {
108
+ throw ( new Error('Should never happen since node is incompressible'));
109
+ }
110
+ disposeElement(element, index, templateData, details) {
111
+ templateData.elementDisposables.clear();
112
+ }
113
+ disposeTemplate(templateData) {
114
+ templateData.elementDisposables.dispose();
115
+ templateData.templateDisposable.dispose();
116
+ }
117
+ };
118
+ ArtifactGroupRenderer = ArtifactGroupRenderer_1 = ( __decorate([
119
+ ( __param(0, IContextMenuService)),
120
+ ( __param(1, IContextKeyService)),
121
+ ( __param(2, IKeybindingService)),
122
+ ( __param(3, IMenuService)),
123
+ ( __param(4, ICommandService)),
124
+ ( __param(5, ISCMViewService)),
125
+ ( __param(6, ITelemetryService))
126
+ ], ArtifactGroupRenderer));
127
+ let ArtifactRenderer = class ArtifactRenderer {
128
+ static { ArtifactRenderer_1 = this; }
129
+ static { this.TEMPLATE_ID = 'artifact'; }
130
+ get templateId() { return ArtifactRenderer_1.TEMPLATE_ID; }
131
+ constructor(_contextMenuService, _contextKeyService, _keybindingService, _menuService, _commandService, _scmViewService, _telemetryService) {
132
+ this._contextMenuService = _contextMenuService;
133
+ this._contextKeyService = _contextKeyService;
134
+ this._keybindingService = _keybindingService;
135
+ this._menuService = _menuService;
136
+ this._commandService = _commandService;
137
+ this._scmViewService = _scmViewService;
138
+ this._telemetryService = _telemetryService;
139
+ }
140
+ renderTemplate(container) {
141
+ const element = append(container, $('.scm-artifact'));
142
+ const icon = append(element, $('.icon'));
143
+ const label = ( new IconLabel(element, { supportIcons: false }));
144
+ const actionsContainer = append(element, $('.actions'));
145
+ const actionBar = ( new WorkbenchToolBar(
146
+ actionsContainer,
147
+ undefined,
148
+ this._menuService,
149
+ this._contextKeyService,
150
+ this._contextMenuService,
151
+ this._keybindingService,
152
+ this._commandService,
153
+ this._telemetryService
154
+ ));
155
+ return { icon, label, actionBar, elementDisposables: ( new DisposableStore()), templateDisposable: combinedDisposable(label, actionBar) };
156
+ }
157
+ renderElement(nodeOrElement, index, templateData) {
158
+ const artifactOrFolder = nodeOrElement.element;
159
+ if (isSCMArtifactTreeElement(artifactOrFolder)) {
160
+ const artifact = artifactOrFolder.artifact;
161
+ const artifactIcon = artifact.icon ?? artifactOrFolder.group.icon;
162
+ templateData.icon.className = ThemeIcon.isThemeIcon(artifactIcon)
163
+ ? `icon ${ThemeIcon.asClassName(artifactIcon)}`
164
+ : '';
165
+ const artifactLabel = artifact.name.split('/').pop() ?? artifact.name;
166
+ templateData.label.setLabel(artifactLabel, artifact.description);
167
+ }
168
+ else if (isSCMArtifactNode(artifactOrFolder)) {
169
+ templateData.icon.className = `icon ${ThemeIcon.asClassName(Codicon.folder)}`;
170
+ templateData.label.setLabel(basename(artifactOrFolder.uri));
171
+ }
172
+ this._renderActionBar(artifactOrFolder, templateData);
173
+ }
174
+ renderCompressedElements(node, index, templateData, details) {
175
+ const compressed = node.element;
176
+ const artifactOrFolder = compressed.elements[compressed.elements.length - 1];
177
+ if (isSCMArtifactTreeElement(artifactOrFolder)) {
178
+ const artifact = artifactOrFolder.artifact;
179
+ const artifactIcon = artifact.icon ?? artifactOrFolder.group.icon;
180
+ templateData.icon.className = ThemeIcon.isThemeIcon(artifactIcon)
181
+ ? `icon ${ThemeIcon.asClassName(artifactIcon)}`
182
+ : '';
183
+ templateData.label.setLabel(artifact.name, artifact.description);
184
+ }
185
+ else if (isSCMArtifactNode(artifactOrFolder)) {
186
+ templateData.icon.className = `icon ${ThemeIcon.asClassName(Codicon.folder)}`;
187
+ templateData.label.setLabel(artifactOrFolder.uri.fsPath.substring(1));
188
+ }
189
+ this._renderActionBar(artifactOrFolder, templateData);
190
+ }
191
+ _renderActionBar(artifactOrFolder, templateData) {
192
+ if (isSCMArtifactTreeElement(artifactOrFolder)) {
193
+ const artifact = artifactOrFolder.artifact;
194
+ const provider = artifactOrFolder.repository.provider;
195
+ const repositoryMenus = this._scmViewService.menus.getRepositoryMenus(provider);
196
+ templateData.elementDisposables.add(connectPrimaryMenu(repositoryMenus.getArtifactMenu(artifactOrFolder.group, artifact), primary => {
197
+ templateData.actionBar.setActions(primary);
198
+ }, 'inline', provider));
199
+ templateData.actionBar.context = artifact;
200
+ }
201
+ else if (ResourceTree.isResourceNode(artifactOrFolder)) {
202
+ templateData.actionBar.setActions([]);
203
+ templateData.actionBar.context = undefined;
204
+ }
205
+ }
206
+ disposeElement(element, index, templateData, details) {
207
+ templateData.elementDisposables.clear();
208
+ }
209
+ disposeTemplate(templateData) {
210
+ templateData.elementDisposables.dispose();
211
+ templateData.templateDisposable.dispose();
212
+ }
213
+ };
214
+ ArtifactRenderer = ArtifactRenderer_1 = ( __decorate([
215
+ ( __param(0, IContextMenuService)),
216
+ ( __param(1, IContextKeyService)),
217
+ ( __param(2, IKeybindingService)),
218
+ ( __param(3, IMenuService)),
219
+ ( __param(4, ICommandService)),
220
+ ( __param(5, ISCMViewService)),
221
+ ( __param(6, ITelemetryService))
222
+ ], ArtifactRenderer));
41
223
  let RepositoryTreeDataSource = class RepositoryTreeDataSource extends Disposable {
42
224
  constructor(scmViewService) {
43
225
  super();
44
226
  this.scmViewService = scmViewService;
45
227
  }
46
- getChildren(inputOrElement) {
47
- const parentId = isSCMRepository(inputOrElement)
48
- ? inputOrElement.provider.id
49
- : undefined;
50
- const repositories = this.scmViewService.repositories
51
- .filter(r => r.provider.parentId === parentId);
52
- return repositories;
228
+ async getChildren(inputOrElement) {
229
+ if (this.scmViewService.explorerEnabledConfig.get() === false) {
230
+ const parentId = isSCMRepository(inputOrElement)
231
+ ? inputOrElement.provider.id
232
+ : undefined;
233
+ const repositories = this.scmViewService.repositories
234
+ .filter(r => r.provider.parentId === parentId);
235
+ return repositories;
236
+ }
237
+ if (inputOrElement instanceof SCMViewService) {
238
+ const repositories = this.scmViewService.repositories
239
+ .filter(r => r.provider.parentId === undefined);
240
+ if (repositories.length !== this.scmViewService.repositories.length) {
241
+ for (const repository of repositories) {
242
+ const childRepositories = this.scmViewService.repositories
243
+ .filter(r => r.provider.parentId === repository.provider.id);
244
+ if (childRepositories.length === 0) {
245
+ continue;
246
+ }
247
+ const repositoryIndex = repositories.indexOf(repository);
248
+ repositories.splice(repositoryIndex + 1, 0, ...childRepositories);
249
+ }
250
+ }
251
+ return repositories;
252
+ }
253
+ else if (isSCMRepository(inputOrElement)) {
254
+ const artifactGroups = (await inputOrElement.provider.artifactProvider.get()?.provideArtifactGroups()) ?? [];
255
+ return ( artifactGroups.map(group => ({
256
+ repository: inputOrElement,
257
+ artifactGroup: group,
258
+ type: 'artifactGroup'
259
+ })));
260
+ }
261
+ else if (isSCMArtifactGroupTreeElement(inputOrElement)) {
262
+ const repository = inputOrElement.repository;
263
+ const artifacts = (await repository.provider.artifactProvider.get()?.provideArtifacts(inputOrElement.artifactGroup.id)) ?? [];
264
+ const artifactsTree = ( new ResourceTree(inputOrElement));
265
+ for (const artifact of artifacts) {
266
+ artifactsTree.add(( URI.from({
267
+ scheme: 'scm-artifact', path: artifact.name
268
+ })), {
269
+ repository,
270
+ group: inputOrElement.artifactGroup,
271
+ artifact,
272
+ type: 'artifact'
273
+ });
274
+ }
275
+ return ( Iterable.map(artifactsTree.root.children, node => node.element ?? node));
276
+ }
277
+ else if (isSCMArtifactNode(inputOrElement)) {
278
+ return ( Iterable.map(
279
+ inputOrElement.children,
280
+ node => node.element && node.childrenCount === 0 ? node.element : node
281
+ ));
282
+ }
283
+ else ;
284
+ return [];
53
285
  }
54
286
  hasChildren(inputOrElement) {
55
- const parentId = isSCMRepository(inputOrElement)
56
- ? inputOrElement.provider.id
57
- : undefined;
58
- const repositories = this.scmViewService.repositories
59
- .filter(r => r.provider.parentId === parentId);
60
- return repositories.length > 0;
287
+ if (this.scmViewService.explorerEnabledConfig.get() === false) {
288
+ const parentId = isSCMRepository(inputOrElement)
289
+ ? inputOrElement.provider.id
290
+ : undefined;
291
+ const repositories = this.scmViewService.repositories
292
+ .filter(r => r.provider.parentId === parentId);
293
+ return repositories.length > 0;
294
+ }
295
+ if (inputOrElement instanceof SCMViewService) {
296
+ return this.scmViewService.repositories.length > 0;
297
+ }
298
+ else if (isSCMRepository(inputOrElement)) {
299
+ return true;
300
+ }
301
+ else if (isSCMArtifactGroupTreeElement(inputOrElement)) {
302
+ return true;
303
+ }
304
+ else if (isSCMArtifactTreeElement(inputOrElement)) {
305
+ return false;
306
+ }
307
+ else if (isSCMArtifactNode(inputOrElement)) {
308
+ return inputOrElement.childrenCount > 0;
309
+ }
310
+ else {
311
+ return false;
312
+ }
61
313
  }
62
314
  };
63
315
  RepositoryTreeDataSource = ( __decorate([
@@ -65,7 +317,31 @@ RepositoryTreeDataSource = ( __decorate([
65
317
  ], RepositoryTreeDataSource));
66
318
  class RepositoryTreeIdentityProvider {
67
319
  getId(element) {
68
- return element.provider.id;
320
+ if (isSCMRepository(element)) {
321
+ return `repo:${element.provider.id}`;
322
+ }
323
+ else if (isSCMArtifactGroupTreeElement(element)) {
324
+ return `artifactGroup:${element.repository.provider.id}/${element.artifactGroup.id}`;
325
+ }
326
+ else if (isSCMArtifactTreeElement(element)) {
327
+ return `artifact:${element.repository.provider.id}/${element.group.id}/${element.artifact.id}`;
328
+ }
329
+ else if (isSCMArtifactNode(element)) {
330
+ return `artifactFolder:${element.context.repository.provider.id}/${element.context.artifactGroup.id}/${element.uri.fsPath}`;
331
+ }
332
+ else {
333
+ throw ( new Error('Invalid tree element'));
334
+ }
335
+ }
336
+ }
337
+ class RepositoriesTreeCompressionDelegate {
338
+ isIncompressible(element) {
339
+ if (ResourceTree.isResourceNode(element)) {
340
+ return element.childrenCount > 1;
341
+ }
342
+ else {
343
+ return true;
344
+ }
69
345
  }
70
346
  }
71
347
  let SCMRepositoriesViewPane = class SCMRepositoriesViewPane extends ViewPane {
@@ -74,9 +350,12 @@ let SCMRepositoriesViewPane = class SCMRepositoriesViewPane extends ViewPane {
74
350
  this.scmService = scmService;
75
351
  this.scmViewService = scmViewService;
76
352
  this.treeOperationSequencer = ( new Sequencer());
353
+ this.updateChildrenThrottler = ( new Throttler());
77
354
  this.visibilityDisposables = ( new DisposableStore());
355
+ this.repositoryDisposables = ( new DisposableMap());
78
356
  this.visibleCountObs = observableConfigValue('scm.repositories.visible', 10, this.configurationService);
79
357
  this.providerCountBadgeObs = observableConfigValue('scm.providerCountBadge', 'hidden', this.configurationService);
358
+ this._register(this.updateChildrenThrottler);
80
359
  }
81
360
  renderBody(container) {
82
361
  super.renderBody(container);
@@ -98,20 +377,11 @@ let SCMRepositoriesViewPane = class SCMRepositoriesViewPane extends ViewPane {
98
377
  const visibleCount = this.visibleCountObs.read(reader);
99
378
  this.updateBodySize(this.tree.contentHeight, visibleCount);
100
379
  }));
101
- const addedRepositoryObs = observableFromEvent(this, this.scmService.onDidAddRepository, e => e);
102
- const removedRepositoryObs = observableFromEvent(this, this.scmService.onDidRemoveRepository, e => e);
103
- this.visibilityDisposables.add(autorun(async (reader) => {
104
- const addedRepository = addedRepositoryObs.read(reader);
105
- const removedRepository = removedRepositoryObs.read(reader);
106
- if (addedRepository === undefined && removedRepository === undefined) {
107
- await this.updateChildren();
108
- return;
109
- }
110
- if (addedRepository) {
111
- await this.updateRepository(addedRepository);
112
- }
113
- if (removedRepository) {
114
- await this.updateRepository(removedRepository);
380
+ this.visibilityDisposables.add(runOnChange(this.scmViewService.explorerEnabledConfig, async () => {
381
+ await this.updateChildren();
382
+ this.updateBodySize(this.tree.contentHeight);
383
+ if (this.scmViewService.repositories.length === 1) {
384
+ await this.treeOperationSequencer.queue(() => this.tree.expand(this.scmViewService.repositories[0]));
115
385
  }
116
386
  }));
117
387
  const onDidChangeVisibleRepositoriesSignal = observableSignalFromEvent(this, this.scmViewService.onDidChangeVisibleRepositories);
@@ -119,6 +389,11 @@ let SCMRepositoriesViewPane = class SCMRepositoriesViewPane extends ViewPane {
119
389
  onDidChangeVisibleRepositoriesSignal.read(reader);
120
390
  await this.treeOperationSequencer.queue(() => this.updateTreeSelection());
121
391
  }));
392
+ this.scmService.onDidAddRepository(this.onDidAddRepository, this, this.visibilityDisposables);
393
+ this.scmService.onDidRemoveRepository(this.onDidRemoveRepository, this, this.visibilityDisposables);
394
+ for (const repository of this.scmService.repositories) {
395
+ this.onDidAddRepository(repository);
396
+ }
122
397
  });
123
398
  }, this, this._store);
124
399
  }
@@ -134,78 +409,155 @@ let SCMRepositoriesViewPane = class SCMRepositoriesViewPane extends ViewPane {
134
409
  this.treeIdentityProvider = ( new RepositoryTreeIdentityProvider());
135
410
  this.treeDataSource = this.instantiationService.createInstance(RepositoryTreeDataSource);
136
411
  this._register(this.treeDataSource);
137
- const compressionEnabled = observableConfigValue('scm.compactFolders', true, this.configurationService);
138
- this.tree = this.instantiationService.createInstance(WorkbenchCompressibleAsyncDataTree, 'SCM Repositories', container, ( new ListDelegate()), {
139
- isIncompressible: () => true
140
- }, [
141
- this.instantiationService.createInstance(RepositoryRenderer, MenuId.SCMSourceControlInline, getActionViewItemProvider(this.instantiationService))
412
+ this.tree = this.instantiationService.createInstance(WorkbenchCompressibleAsyncDataTree, 'SCM Repositories', container, ( new ListDelegate()), ( new RepositoriesTreeCompressionDelegate()), [
413
+ this.instantiationService.createInstance(RepositoryRenderer, MenuId.SCMSourceControlInline, getActionViewItemProvider(this.instantiationService)),
414
+ this.instantiationService.createInstance(ArtifactGroupRenderer),
415
+ this.instantiationService.createInstance(ArtifactRenderer)
142
416
  ], this.treeDataSource, {
143
417
  identityProvider: this.treeIdentityProvider,
144
418
  horizontalScrolling: false,
145
419
  collapseByDefault: (e) => {
146
- if (isSCMRepository(e) && e.provider.parentId === undefined) {
147
- return false;
420
+ if (this.scmViewService.explorerEnabledConfig.get() === false) {
421
+ if (isSCMRepository(e) && e.provider.parentId === undefined) {
422
+ return false;
423
+ }
424
+ return true;
425
+ }
426
+ if (isSCMArtifactNode(e)) {
427
+ return !(e.childrenCount === 1 && Iterable.first(e.children)?.element === undefined);
428
+ }
429
+ else {
430
+ return true;
148
431
  }
149
- return true;
150
432
  },
151
- compressionEnabled: compressionEnabled.get(),
433
+ compressionEnabled: true,
152
434
  overrideStyles: this.getLocationBasedColors().listOverrideStyles,
153
- expandOnDoubleClick: false,
435
+ multipleSelectionSupport: this.scmViewService.selectionModeConfig.get() === 'multiple',
436
+ expandOnDoubleClick: true,
154
437
  expandOnlyOnTwistieClick: true,
155
438
  accessibilityProvider: {
156
- getAriaLabel(r) {
157
- return r.provider.label;
439
+ getAriaLabel(element) {
440
+ if (isSCMRepository(element)) {
441
+ return element.provider.label;
442
+ }
443
+ else if (isSCMArtifactGroupTreeElement(element)) {
444
+ return element.artifactGroup.name;
445
+ }
446
+ else if (isSCMArtifactTreeElement(element)) {
447
+ return element.artifact.name;
448
+ }
449
+ else {
450
+ return '';
451
+ }
158
452
  },
159
453
  getWidgetAriaLabel() {
160
- return localize(10148, "Source Control Repositories");
454
+ return localize(10423, "Source Control Repositories");
161
455
  }
162
456
  }
163
457
  });
164
458
  this._register(this.tree);
459
+ this._register(autorun(reader => {
460
+ const selectionMode = this.scmViewService.selectionModeConfig.read(reader);
461
+ this.tree.updateOptions({ multipleSelectionSupport: selectionMode === 'multiple' });
462
+ }));
165
463
  this._register(this.tree.onDidChangeSelection(this.onTreeSelectionChange, this));
166
464
  this._register(this.tree.onDidChangeFocus(this.onTreeDidChangeFocus, this));
167
465
  this._register(this.tree.onDidFocus(this.onDidTreeFocus, this));
168
466
  this._register(this.tree.onContextMenu(this.onTreeContextMenu, this));
169
467
  this._register(this.tree.onDidChangeContentHeight(this.onTreeContentHeightChange, this));
170
468
  }
469
+ async onDidAddRepository(repository) {
470
+ const disposables = ( new DisposableStore());
471
+ disposables.add(autorun(async (reader) => {
472
+ const explorerEnabled = this.scmViewService.explorerEnabledConfig.read(reader);
473
+ const artifactsProvider = repository.provider.artifactProvider.read(reader);
474
+ if (!explorerEnabled || !artifactsProvider) {
475
+ return;
476
+ }
477
+ reader.store.add(artifactsProvider.onDidChangeArtifacts(async (groups) => {
478
+ await this.updateRepository(repository);
479
+ }));
480
+ }));
481
+ disposables.add(autorun(async (reader) => {
482
+ const historyProvider = repository.provider.historyProvider.read(reader);
483
+ if (!historyProvider) {
484
+ return;
485
+ }
486
+ reader.store.add(runOnChange(historyProvider.historyItemRef, async () => {
487
+ await this.updateRepository(repository);
488
+ }));
489
+ }));
490
+ await this.updateRepository(repository);
491
+ this.repositoryDisposables.set(repository, disposables);
492
+ }
493
+ async onDidRemoveRepository(repository) {
494
+ await this.updateRepository(repository);
495
+ this.repositoryDisposables.deleteAndDispose(repository);
496
+ }
171
497
  onTreeContextMenu(e) {
172
498
  if (!e.element) {
173
499
  return;
174
500
  }
175
- const provider = e.element.provider;
176
- const menus = this.scmViewService.menus.getRepositoryMenus(provider);
177
- const menu = menus.getRepositoryContextMenu(e.element);
178
- const actions = collectContextMenuActions(menu);
179
- const disposables = ( new DisposableStore());
180
- const actionRunner = ( new RepositoryActionRunner(() => {
181
- return this.tree.getSelection();
182
- }));
183
- disposables.add(actionRunner);
184
- disposables.add(actionRunner.onWillRun(() => this.tree.domFocus()));
185
- this.contextMenuService.showContextMenu({
186
- actionRunner,
187
- getAnchor: () => e.anchor,
188
- getActions: () => actions,
189
- getActionsContext: () => provider,
190
- onHide: () => disposables.dispose()
191
- });
501
+ if (isSCMRepository(e.element)) {
502
+ const provider = e.element.provider;
503
+ const menus = this.scmViewService.menus.getRepositoryMenus(provider);
504
+ const menu = menus.getRepositoryContextMenu(e.element);
505
+ const actions = collectContextMenuActions(menu);
506
+ const disposables = ( new DisposableStore());
507
+ const actionRunner = ( new RepositoryActionRunner(() => {
508
+ return this.getTreeSelection();
509
+ }));
510
+ disposables.add(actionRunner);
511
+ disposables.add(actionRunner.onWillRun(() => this.tree.domFocus()));
512
+ this.contextMenuService.showContextMenu({
513
+ actionRunner,
514
+ getAnchor: () => e.anchor,
515
+ getActions: () => actions,
516
+ getActionsContext: () => provider,
517
+ onHide: () => disposables.dispose()
518
+ });
519
+ }
520
+ else if (isSCMArtifactTreeElement(e.element)) {
521
+ const provider = e.element.repository.provider;
522
+ const artifact = e.element.artifact;
523
+ const menus = this.scmViewService.menus.getRepositoryMenus(provider);
524
+ const menu = menus.getArtifactMenu(e.element.group, artifact);
525
+ const actions = collectContextMenuActions(menu, provider);
526
+ this.contextMenuService.showContextMenu({
527
+ getAnchor: () => e.anchor,
528
+ getActions: () => actions,
529
+ getActionsContext: () => artifact
530
+ });
531
+ }
192
532
  }
193
533
  onTreeSelectionChange(e) {
194
534
  if (e.browserEvent && e.elements.length > 0) {
195
535
  const scrollTop = this.tree.scrollTop;
196
- this.scmViewService.visibleRepositories = e.elements;
536
+ if (e.elements.every(e => isSCMRepository(e))) {
537
+ this.scmViewService.visibleRepositories = e.elements;
538
+ }
539
+ else if (e.elements.every(e => isSCMArtifactGroupTreeElement(e) || isSCMArtifactTreeElement(e))) {
540
+ this.scmViewService.visibleRepositories = ( e.elements.map(e => e.repository));
541
+ }
197
542
  this.tree.scrollTop = scrollTop;
198
543
  }
199
544
  }
200
545
  onTreeDidChangeFocus(e) {
201
546
  if (e.browserEvent && e.elements.length > 0) {
202
- this.scmViewService.focus(e.elements[0]);
547
+ if (isSCMRepository(e.elements[0])) {
548
+ this.scmViewService.focus(e.elements[0]);
549
+ }
203
550
  }
204
551
  }
205
552
  onDidTreeFocus() {
206
553
  const focused = this.tree.getFocus();
207
554
  if (focused.length > 0) {
208
- this.scmViewService.focus(focused[0]);
555
+ if (isSCMRepository(focused[0])) {
556
+ this.scmViewService.focus(focused[0]);
557
+ }
558
+ else if (isSCMArtifactGroupTreeElement(focused[0]) || isSCMArtifactTreeElement(focused[0])) {
559
+ this.scmViewService.focus(focused[0].repository);
560
+ }
209
561
  }
210
562
  }
211
563
  onTreeContentHeightChange(height) {
@@ -213,24 +565,27 @@ let SCMRepositoriesViewPane = class SCMRepositoriesViewPane extends ViewPane {
213
565
  this.treeOperationSequencer.queue(() => this.updateTreeSelection());
214
566
  }
215
567
  async updateChildren(element) {
216
- await this.treeOperationSequencer.queue(async () => {
568
+ return this.updateChildrenThrottler.queue(() => this.treeOperationSequencer.queue(async () => {
217
569
  if (element && this.tree.hasNode(element)) {
218
570
  await this.tree.updateChildren(element, true);
219
571
  }
220
572
  else {
221
573
  await this.tree.updateChildren(undefined, true);
222
574
  }
223
- });
575
+ }));
224
576
  }
225
577
  async expand(element) {
226
578
  await this.treeOperationSequencer.queue(() => this.tree.expand(element, true));
227
579
  }
228
580
  async updateRepository(repository) {
229
- if (repository.provider.parentId === undefined) {
230
- await this.updateChildren();
231
- return;
581
+ if (this.scmViewService.explorerEnabledConfig.get() === false) {
582
+ if (repository.provider.parentId === undefined) {
583
+ await this.updateChildren();
584
+ return;
585
+ }
586
+ await this.updateParentRepository(repository);
232
587
  }
233
- await this.updateParentRepository(repository);
588
+ await this.updateChildren();
234
589
  }
235
590
  async updateParentRepository(repository) {
236
591
  const parentRepository = this.scmViewService.repositories
@@ -245,14 +600,20 @@ let SCMRepositoriesViewPane = class SCMRepositoriesViewPane extends ViewPane {
245
600
  if (this.orientation === Orientation.HORIZONTAL) {
246
601
  return;
247
602
  }
248
- visibleCount = visibleCount ?? this.visibleCountObs.get();
249
- const empty = this.scmViewService.repositories.length === 0;
250
- const size = Math.min(contentHeight / 22, visibleCount) * 22;
251
- this.minimumBodySize = visibleCount === 0 ? 22 : size;
252
- this.maximumBodySize = visibleCount === 0 ? Number.POSITIVE_INFINITY : empty ? Number.POSITIVE_INFINITY : size;
603
+ if (this.scmViewService.explorerEnabledConfig.get() === false) {
604
+ visibleCount = visibleCount ?? this.visibleCountObs.get();
605
+ const empty = this.scmViewService.repositories.length === 0;
606
+ const size = Math.min(contentHeight / 22, visibleCount) * 22;
607
+ this.minimumBodySize = visibleCount === 0 ? 22 : size;
608
+ this.maximumBodySize = visibleCount === 0 ? Number.POSITIVE_INFINITY : empty ? Number.POSITIVE_INFINITY : size;
609
+ }
610
+ else {
611
+ this.minimumBodySize = 120;
612
+ this.maximumBodySize = Number.POSITIVE_INFINITY;
613
+ }
253
614
  }
254
615
  async updateTreeSelection() {
255
- const oldSelection = this.tree.getSelection();
616
+ const oldSelection = this.getTreeSelection();
256
617
  const oldSet = ( new Set(oldSelection));
257
618
  const set = ( new Set(this.scmViewService.visibleRepositories));
258
619
  const added = ( new Set(Iterable.filter(set, r => !( oldSet.has(r)))));
@@ -274,6 +635,23 @@ let SCMRepositoriesViewPane = class SCMRepositoriesViewPane extends ViewPane {
274
635
  this.tree.setFocus([visibleSelection[0]]);
275
636
  }
276
637
  }
638
+ getTreeSelection() {
639
+ return ( this.tree.getSelection()
640
+ .map(e => {
641
+ if (isSCMRepository(e)) {
642
+ return e;
643
+ }
644
+ else if (isSCMArtifactGroupTreeElement(e) || isSCMArtifactTreeElement(e)) {
645
+ return e.repository;
646
+ }
647
+ else if (isSCMArtifactNode(e)) {
648
+ return e.context.repository;
649
+ }
650
+ else {
651
+ throw ( new Error('Invalid tree element'));
652
+ }
653
+ }));
654
+ }
277
655
  dispose() {
278
656
  this.visibilityDisposables.dispose();
279
657
  super.dispose();