@codingame/monaco-vscode-scm-service-override 17.2.0 → 18.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 (26) hide show
  1. package/package.json +15 -13
  2. package/vscode/src/vs/workbench/contrib/scm/browser/activity.js +10 -10
  3. package/vscode/src/vs/workbench/contrib/scm/browser/media/scm.css +33 -3
  4. package/vscode/src/vs/workbench/contrib/scm/browser/menus.js +1 -1
  5. package/vscode/src/vs/workbench/contrib/scm/browser/quickDiffDecorator.js +7 -7
  6. package/vscode/src/vs/workbench/contrib/scm/browser/quickDiffModel.d.ts +6 -4
  7. package/vscode/src/vs/workbench/contrib/scm/browser/quickDiffModel.js +53 -32
  8. package/vscode/src/vs/workbench/contrib/scm/browser/quickDiffWidget.d.ts +4 -3
  9. package/vscode/src/vs/workbench/contrib/scm/browser/quickDiffWidget.js +57 -52
  10. package/vscode/src/vs/workbench/contrib/scm/browser/scm.contribution.js +89 -82
  11. package/vscode/src/vs/workbench/contrib/scm/browser/scmAccessibilityHelp.js +23 -23
  12. package/vscode/src/vs/workbench/contrib/scm/browser/scmHistoryChatContext.d.ts +9 -0
  13. package/vscode/src/vs/workbench/contrib/scm/browser/scmHistoryChatContext.js +185 -0
  14. package/vscode/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.d.ts +7 -5
  15. package/vscode/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.js +414 -158
  16. package/vscode/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.d.ts +1 -1
  17. package/vscode/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.js +3 -3
  18. package/vscode/src/vs/workbench/contrib/scm/browser/scmRepositoryRenderer.d.ts +3 -3
  19. package/vscode/src/vs/workbench/contrib/scm/browser/scmRepositoryRenderer.js +3 -3
  20. package/vscode/src/vs/workbench/contrib/scm/browser/scmViewPane.d.ts +5 -8
  21. package/vscode/src/vs/workbench/contrib/scm/browser/scmViewPane.js +82 -45
  22. package/vscode/src/vs/workbench/contrib/scm/browser/scmViewPaneContainer.d.ts +1 -1
  23. package/vscode/src/vs/workbench/contrib/scm/browser/scmViewPaneContainer.js +1 -1
  24. package/vscode/src/vs/workbench/contrib/scm/browser/scmViewService.js +6 -4
  25. package/vscode/src/vs/workbench/contrib/scm/browser/workingSet.js +3 -3
  26. package/vscode/src/vs/workbench/contrib/scm/common/scmService.js +1 -1
@@ -2,13 +2,10 @@
2
2
  import { registerCss } from '@codingame/monaco-vscode-api/css';
3
3
  import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
4
4
  import * as scm from './media/scm.css';
5
- import { language } from '@codingame/monaco-vscode-api/vscode/vs/base/common/platform';
6
5
  import { $, reset, append, h } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/dom';
7
6
  import { IconLabel } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/iconLabel/iconLabel';
8
- import { safeIntl, fromNow } from '@codingame/monaco-vscode-api/vscode/vs/base/common/date';
9
7
  import { createMatches } from '@codingame/monaco-vscode-api/vscode/vs/base/common/filters';
10
- import { MarkdownString } from '@codingame/monaco-vscode-api/vscode/vs/base/common/htmlContent';
11
- import { DisposableStore, Disposable, MutableDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
8
+ import { combinedDisposable, DisposableStore, Disposable, MutableDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
12
9
  import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
13
10
  import { ThemeIcon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/themables';
14
11
  import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
@@ -20,7 +17,7 @@ import { WorkbenchHoverDelegate } from '@codingame/monaco-vscode-api/vscode/vs/p
20
17
  import { IHoverService } from '@codingame/monaco-vscode-api/vscode/vs/platform/hover/browser/hover.service';
21
18
  import { IInstantiationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation';
22
19
  import { IKeybindingService } from '@codingame/monaco-vscode-api/vscode/vs/platform/keybinding/common/keybinding.service';
23
- import { WorkbenchAsyncDataTree } from '@codingame/monaco-vscode-api/vscode/vs/platform/list/browser/listService';
20
+ import { WorkbenchCompressibleAsyncDataTree } from '@codingame/monaco-vscode-api/vscode/vs/platform/list/browser/listService';
24
21
  import { IOpenerService } from '@codingame/monaco-vscode-api/vscode/vs/platform/opener/common/opener.service';
25
22
  import { asCssVariable } from '@codingame/monaco-vscode-api/vscode/vs/platform/theme/common/colorUtils';
26
23
  import { foreground } from '@codingame/monaco-vscode-api/vscode/vs/platform/theme/common/colors/baseColors';
@@ -34,12 +31,12 @@ import '@codingame/monaco-vscode-api/vscode/vs/platform/theme/common/colors/misc
34
31
  import '@codingame/monaco-vscode-api/vscode/vs/platform/theme/common/colors/quickpickColors';
35
32
  import '@codingame/monaco-vscode-api/vscode/vs/platform/theme/common/colors/searchColors';
36
33
  import { IThemeService } from '@codingame/monaco-vscode-api/vscode/vs/platform/theme/common/themeService.service';
37
- import { ViewAction, ViewPane, ViewPaneShowActions } from '@codingame/monaco-vscode-65619f8f-0eab-5d8b-855a-43b6353fe527-common/vscode/vs/workbench/browser/parts/views/viewPane';
34
+ import { ViewAction, ViewPane, ViewPaneShowActions } from '@codingame/monaco-vscode-501b06ab-3f58-516b-8a1a-c29d375d3da4-common/vscode/vs/workbench/browser/parts/views/viewPane';
38
35
  import { ViewContainerLocation } from '@codingame/monaco-vscode-api/vscode/vs/workbench/common/views';
39
36
  import { IViewDescriptorService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/common/views.service';
40
- import { renderSCMHistoryItemGraph, historyItemHoverDefaultLabelBackground, historyItemHoverLabelForeground, historyItemHoverAdditionsForeground, historyItemHoverDeletionsForeground, historyItemHoverDefaultLabelForeground, SWIMLANE_WIDTH, renderSCMHistoryGraphPlaceholder, toISCMHistoryItemViewModelArray } from '@codingame/monaco-vscode-be8ddbb5-094a-5657-b1cc-fe106c94c632-common/vscode/vs/workbench/contrib/scm/browser/scmHistory';
41
- import { getHistoryItemEditorTitle, isSCMHistoryItemViewModelTreeElement, isSCMHistoryItemLoadMoreTreeElement, isSCMRepository, getProviderKey } from '@codingame/monaco-vscode-be8ddbb5-094a-5657-b1cc-fe106c94c632-common/vscode/vs/workbench/contrib/scm/browser/util';
42
- import { HISTORY_VIEW_PANE_ID } from '@codingame/monaco-vscode-ff9fa663-eae3-5274-8573-c2b918871e4b-common/vscode/vs/workbench/contrib/scm/common/scm';
37
+ import { renderSCMHistoryItemGraph, historyItemHoverDefaultLabelBackground, historyItemHoverLabelForeground, SWIMLANE_WIDTH, renderSCMHistoryGraphPlaceholder, getHistoryItemIndex, toISCMHistoryItemViewModelArray } from '@codingame/monaco-vscode-7adbeffb-8051-54a9-8c9b-b62ce9e5836f-common/vscode/vs/workbench/contrib/scm/browser/scmHistory';
38
+ import { getHistoryItemEditorTitle, isSCMHistoryItemViewModelTreeElement, isSCMHistoryItemChangeViewModelTreeElement, isSCMHistoryItemChangeNode, isSCMHistoryItemLoadMoreTreeElement, getHistoryItemHoverContent, isSCMRepository, getProviderKey } from '@codingame/monaco-vscode-7adbeffb-8051-54a9-8c9b-b62ce9e5836f-common/vscode/vs/workbench/contrib/scm/browser/util';
39
+ import { HISTORY_VIEW_PANE_ID, ViewMode } from '@codingame/monaco-vscode-ff9fa663-eae3-5274-8573-c2b918871e4b-common/vscode/vs/workbench/contrib/scm/common/scm';
43
40
  import { ISCMService, ISCMViewService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/scm/common/scm.service';
44
41
  import { stripIcons } from '@codingame/monaco-vscode-api/vscode/vs/base/common/iconLabels';
45
42
  import { Position } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/layout/browser/layoutService';
@@ -48,7 +45,6 @@ import { HoverPosition } from '@codingame/monaco-vscode-api/vscode/vs/base/brows
48
45
  import { registerAction2, MenuId, Action2, MenuRegistry, isIMenuItem } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/common/actions';
49
46
  import { IMenuService } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/common/actions.service';
50
47
  import { Sequencer, Throttler } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
51
- import { URI } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uri';
52
48
  import { ICommandService } from '@codingame/monaco-vscode-api/vscode/vs/platform/commands/common/commands.service';
53
49
  import { ActionRunner } from '@codingame/monaco-vscode-api/vscode/vs/base/common/actions';
54
50
  import { delta, groupBy as groupBy$1 } from '@codingame/monaco-vscode-api/vscode/vs/base/common/arrays';
@@ -68,14 +64,28 @@ import { StorageScope, StorageTarget } from '@codingame/monaco-vscode-api/vscode
68
64
  import { IStorageService } from '@codingame/monaco-vscode-api/vscode/vs/platform/storage/common/storage.service';
69
65
  import { IExtensionService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensions/common/extensions.service';
70
66
  import { groupBy } from '@codingame/monaco-vscode-api/vscode/vs/base/common/collections';
71
- import { getFlatContextMenuActions } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/browser/menuEntryActionViewItem';
72
- import { autorun, autorunWithStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/autorun';
73
- import { observableValue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/base';
74
- import { waitForState } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/utilsCancellation';
75
- import { derived } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/derived';
76
- import { observableSignal, constObservable, observableFromEvent, latestChangedValue, runOnChange } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/utils';
67
+ import { getActionBarActions, getFlatContextMenuActions } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/browser/menuEntryActionViewItem';
68
+ import { ResourceLabels } from '@codingame/monaco-vscode-f24b7f0a-ceeb-5877-9148-81eb98a4f5d7-common/vscode/vs/workbench/browser/labels';
69
+ import { FileKind } from '@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files';
70
+ import { WorkbenchToolBar } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/browser/toolbar';
71
+ import { ITelemetryService } from '@codingame/monaco-vscode-api/vscode/vs/platform/telemetry/common/telemetry.service';
72
+ import { basename } from '@codingame/monaco-vscode-api/vscode/vs/base/common/path';
73
+ import { IEditorService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/editor/common/editorService.service';
74
+ import { ScmHistoryItemResolver } from '@codingame/monaco-vscode-f99b74f5-fcb7-512f-8c6c-35f5a107577d-common/vscode/vs/workbench/contrib/multiDiffEditor/browser/scmMultiDiffSourceResolver';
75
+ import { ResourceTree } from '@codingame/monaco-vscode-7adbeffb-8051-54a9-8c9b-b62ce9e5836f-common/vscode/vs/base/common/resourceTree';
76
+ import { URI } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uri';
77
+ import { ILabelService } from '@codingame/monaco-vscode-api/vscode/vs/platform/label/common/label.service';
78
+ import { autorun, autorunWithStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/reactions/autorun';
79
+ import { observableValue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableValue';
80
+ import { waitForState } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/utils/utilsCancellation';
81
+ import { observableFromEvent } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableFromEvent';
82
+ import { observableSignal } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableSignal';
83
+ import { constObservable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/constObservable';
84
+ import { latestChangedValue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/experimental/utils';
85
+ import { derived } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/derived';
86
+ import { runOnChange } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/utils/runOnChange';
77
87
 
78
- var HistoryItemRenderer_1, HistoryItemLoadMoreRenderer_1;
88
+ var HistoryItemRenderer_1, HistoryItemChangeRenderer_1, HistoryItemLoadMoreRenderer_1;
79
89
  registerCss(scm);
80
90
  const PICK_REPOSITORY_ACTION_ID = 'workbench.scm.action.graph.pickRepository';
81
91
  const PICK_HISTORY_ITEM_REFS_ACTION_ID = 'workbench.scm.action.graph.pickHistoryItemRefs';
@@ -111,23 +121,23 @@ class SCMHistoryItemRefsActionViewItem extends ActionViewItem {
111
121
  icon.classList.add(...ThemeIcon.asClassNameArray(Codicon.gitBranch));
112
122
  const name = $('.name');
113
123
  if (this._historyItemsFilter === 'all') {
114
- name.textContent = ( localize(9211, "All"));
124
+ name.textContent = ( localize(9454, "All"));
115
125
  }
116
126
  else if (this._historyItemsFilter === 'auto') {
117
- name.textContent = ( localize(9212, "Auto"));
127
+ name.textContent = ( localize(9455, "Auto"));
118
128
  }
119
129
  else if (this._historyItemsFilter.length === 1) {
120
130
  name.textContent = this._historyItemsFilter[0].name;
121
131
  }
122
132
  else {
123
- name.textContent = ( localize(9213, "{0} Items", this._historyItemsFilter.length));
133
+ name.textContent = ( localize(9456, "{0} Items", this._historyItemsFilter.length));
124
134
  }
125
135
  reset(this.label, icon, name);
126
136
  }
127
137
  }
128
138
  getTooltip() {
129
139
  if (this._historyItemsFilter === 'all') {
130
- return localize(9214, "All history item references");
140
+ return localize(9457, "All history item references");
131
141
  }
132
142
  else if (this._historyItemsFilter === 'auto') {
133
143
  const historyProvider = this._repository.provider.historyProvider.get();
@@ -149,7 +159,7 @@ registerAction2(class extends ViewAction {
149
159
  constructor() {
150
160
  super({
151
161
  id: PICK_REPOSITORY_ACTION_ID,
152
- title: ( localize(9215, "Repository Picker")),
162
+ title: ( localize(9458, "Repository Picker")),
153
163
  viewId: HISTORY_VIEW_PANE_ID,
154
164
  f1: false,
155
165
  menu: {
@@ -168,7 +178,7 @@ registerAction2(class extends ViewAction {
168
178
  constructor() {
169
179
  super({
170
180
  id: PICK_HISTORY_ITEM_REFS_ACTION_ID,
171
- title: ( localize(9216, "History Item Reference Picker")),
181
+ title: ( localize(9459, "History Item Reference Picker")),
172
182
  icon: Codicon.gitBranch,
173
183
  viewId: HISTORY_VIEW_PANE_ID,
174
184
  precondition: ( ContextKeys.SCMHistoryItemCount.notEqualsTo(0)),
@@ -188,7 +198,7 @@ registerAction2(class extends ViewAction {
188
198
  constructor() {
189
199
  super({
190
200
  id: 'workbench.scm.action.graph.revealCurrentHistoryItem',
191
- title: ( localize(9217, "Go to Current History Item")),
201
+ title: ( localize(9460, "Go to Current History Item")),
192
202
  icon: Codicon.target,
193
203
  viewId: HISTORY_VIEW_PANE_ID,
194
204
  precondition: ( ContextKeyExpr.and(( ContextKeys.SCMHistoryItemCount.notEqualsTo(0)), ( ContextKeys.SCMCurrentHistoryItemRefInFilter.isEqualTo(true)))),
@@ -208,7 +218,7 @@ registerAction2(class extends ViewAction {
208
218
  constructor() {
209
219
  super({
210
220
  id: 'workbench.scm.action.graph.refresh',
211
- title: ( localize(9218, "Refresh")),
221
+ title: ( localize(9461, "Refresh")),
212
222
  viewId: HISTORY_VIEW_PANE_ID,
213
223
  f1: false,
214
224
  icon: Codicon.refresh,
@@ -223,13 +233,50 @@ registerAction2(class extends ViewAction {
223
233
  view.refresh();
224
234
  }
225
235
  });
236
+ registerAction2(class extends ViewAction {
237
+ constructor() {
238
+ super({
239
+ id: 'workbench.scm.action.graph.setListViewMode',
240
+ title: ( localize(9462, "View as List")),
241
+ viewId: HISTORY_VIEW_PANE_ID,
242
+ toggled: ( ContextKeys.SCMHistoryViewMode.isEqualTo(ViewMode.List)),
243
+ menu: { id: MenuId.SCMHistoryTitle, group: '9_viewmode', order: 1 },
244
+ f1: false
245
+ });
246
+ }
247
+ async runInView(_, view) {
248
+ view.setViewMode(ViewMode.List);
249
+ }
250
+ });
251
+ registerAction2(class extends ViewAction {
252
+ constructor() {
253
+ super({
254
+ id: 'workbench.scm.action.graph.setTreeViewMode',
255
+ title: ( localize(9463, "View as Tree")),
256
+ viewId: HISTORY_VIEW_PANE_ID,
257
+ toggled: ( ContextKeys.SCMHistoryViewMode.isEqualTo(ViewMode.Tree)),
258
+ menu: { id: MenuId.SCMHistoryTitle, group: '9_viewmode', order: 2 },
259
+ f1: false
260
+ });
261
+ }
262
+ async runInView(_, view) {
263
+ view.setViewMode(ViewMode.Tree);
264
+ }
265
+ });
226
266
  registerAction2(class extends Action2 {
227
267
  constructor() {
228
268
  super({
229
269
  id: 'workbench.scm.action.graph.viewChanges',
230
- title: ( localize(9219, "Open Changes")),
270
+ title: ( localize(9464, "Open Changes")),
271
+ icon: Codicon.diffMultiple,
231
272
  f1: false,
232
273
  menu: [
274
+ {
275
+ id: MenuId.SCMHistoryItemContext,
276
+ when: ( ContextKeyExpr.equals('config.multiDiffEditor.experimental.enabled', true)),
277
+ group: 'inline',
278
+ order: 1
279
+ },
233
280
  {
234
281
  id: MenuId.SCMHistoryItemContext,
235
282
  when: ( ContextKeyExpr.equals('config.multiDiffEditor.experimental.enabled', true)),
@@ -253,26 +300,43 @@ registerAction2(class extends Action2 {
253
300
  return;
254
301
  }
255
302
  }
256
- const historyItemParentId = historyItemLast.parentIds.length > 0 ? historyItemLast.parentIds[0] : undefined;
257
- const historyItemChanges = await historyProvider?.provideHistoryItemChanges(historyItem.id, historyItemParentId);
258
- if (!historyItemChanges?.length) {
259
- return;
260
- }
261
303
  const title = historyItems.length === 1 ?
262
304
  getHistoryItemEditorTitle(historyItem) :
263
305
  ( localize(
264
- 9220,
306
+ 9465,
265
307
  "All Changes ({0} ↔ {1})",
266
308
  historyItemLast.displayId ?? historyItemLast.id,
267
309
  historyItem.displayId ?? historyItem.id
268
310
  ));
269
- const rootUri = provider.rootUri;
270
- const path = rootUri ? rootUri.path : provider.label;
271
- const multiDiffSourceUri = ( URI.from(
272
- { scheme: 'scm-history-item', path: `${path}/${historyItemParentId}..${historyItem.id}` },
273
- true
274
- ));
275
- commandService.executeCommand('_workbench.openMultiDiffEditor', { title, multiDiffSourceUri, resources: historyItemChanges });
311
+ const multiDiffSourceUri = ScmHistoryItemResolver.getMultiDiffSourceUri(provider, historyItem);
312
+ commandService.executeCommand('_workbench.openMultiDiffEditor', { title, multiDiffSourceUri });
313
+ }
314
+ });
315
+ registerAction2(class extends Action2 {
316
+ constructor() {
317
+ super({
318
+ id: 'workbench.scm.action.graph.openFile',
319
+ title: ( localize(9466, "Open File")),
320
+ icon: Codicon.goToFile,
321
+ f1: false,
322
+ menu: [
323
+ {
324
+ id: MenuId.SCMHistoryItemChangeContext,
325
+ group: 'inline',
326
+ order: 1
327
+ },
328
+ ]
329
+ });
330
+ }
331
+ async run(accessor, historyItem, historyItemChange) {
332
+ const editorService = accessor.get(IEditorService);
333
+ if (!historyItem || !historyItemChange.modifiedUri) {
334
+ return;
335
+ }
336
+ await editorService.openEditor({
337
+ resource: historyItemChange.modifiedUri,
338
+ label: `${basename(historyItemChange.modifiedUri.fsPath)} (${historyItem.displayId ?? historyItem.id})`,
339
+ });
276
340
  }
277
341
  });
278
342
  class ListDelegate {
@@ -283,6 +347,9 @@ class ListDelegate {
283
347
  if (isSCMHistoryItemViewModelTreeElement(element)) {
284
348
  return HistoryItemRenderer.TEMPLATE_ID;
285
349
  }
350
+ else if (isSCMHistoryItemChangeViewModelTreeElement(element) || isSCMHistoryItemChangeNode(element)) {
351
+ return HistoryItemChangeRenderer.TEMPLATE_ID;
352
+ }
286
353
  else if (isSCMHistoryItemLoadMoreTreeElement(element)) {
287
354
  return HistoryItemLoadMoreRenderer.TEMPLATE_ID;
288
355
  }
@@ -295,13 +362,17 @@ let HistoryItemRenderer = class HistoryItemRenderer {
295
362
  static { HistoryItemRenderer_1 = this; }
296
363
  static { this.TEMPLATE_ID = 'history-item'; }
297
364
  get templateId() { return HistoryItemRenderer_1.TEMPLATE_ID; }
298
- constructor(hoverDelegate, _clipboardService, _configurationService, _contextKeyService, _hoverService, _menuService, _themeService) {
365
+ constructor(hoverDelegate, _clipboardService, _commandService, _configurationService, _contextKeyService, _contextMenuService, _hoverService, _keybindingService, _menuService, _telemetryService, _themeService) {
299
366
  this.hoverDelegate = hoverDelegate;
300
367
  this._clipboardService = _clipboardService;
368
+ this._commandService = _commandService;
301
369
  this._configurationService = _configurationService;
302
370
  this._contextKeyService = _contextKeyService;
371
+ this._contextMenuService = _contextMenuService;
303
372
  this._hoverService = _hoverService;
373
+ this._keybindingService = _keybindingService;
304
374
  this._menuService = _menuService;
375
+ this._telemetryService = _telemetryService;
305
376
  this._themeService = _themeService;
306
377
  this._badgesConfig = observableConfigValue('scm.graph.badges', 'filter', this._configurationService);
307
378
  }
@@ -309,19 +380,28 @@ let HistoryItemRenderer = class HistoryItemRenderer {
309
380
  container.parentElement.parentElement.querySelector('.monaco-tl-twistie').classList.add('force-no-twistie');
310
381
  const element = append(container, $('.history-item'));
311
382
  const graphContainer = append(element, $('.graph-container'));
312
- const iconLabel = ( new IconLabel(
313
- element,
314
- { supportIcons: true, supportHighlights: true, supportDescriptionHighlights: true }
315
- ));
383
+ const iconLabel = ( new IconLabel(element, {
384
+ supportIcons: true, supportHighlights: true, supportDescriptionHighlights: true
385
+ }));
316
386
  const labelContainer = append(element, $('.label-container'));
317
- element.appendChild(labelContainer);
318
- return { element, graphContainer, label: iconLabel, labelContainer, elementDisposables: ( new DisposableStore()), disposables: ( new DisposableStore()) };
387
+ const actionsContainer = append(element, $('.actions'));
388
+ const actionBar = ( new WorkbenchToolBar(
389
+ actionsContainer,
390
+ undefined,
391
+ this._menuService,
392
+ this._contextKeyService,
393
+ this._contextMenuService,
394
+ this._keybindingService,
395
+ this._commandService,
396
+ this._telemetryService
397
+ ));
398
+ return { element, graphContainer, label: iconLabel, labelContainer, actionBar, elementDisposables: ( new DisposableStore()), disposables: combinedDisposable(iconLabel, actionBar) };
319
399
  }
320
- renderElement(node, index, templateData, height) {
400
+ renderElement(node, index, templateData) {
321
401
  const provider = node.element.repository.provider;
322
402
  const historyItemViewModel = node.element.historyItemViewModel;
323
403
  const historyItem = historyItemViewModel.historyItem;
324
- const historyItemHover = this._hoverService.setupManagedHover(this.hoverDelegate, templateData.element, this._getHoverContent(node.element), {
404
+ const historyItemHover = this._hoverService.setupManagedHover(this.hoverDelegate, templateData.element, getHistoryItemHoverContent(this._themeService, historyItem), {
325
405
  actions: this._getHoverActions(provider, historyItem),
326
406
  });
327
407
  templateData.elementDisposables.add(historyItemHover);
@@ -333,6 +413,12 @@ let HistoryItemRenderer = class HistoryItemRenderer {
333
413
  const [matches, descriptionMatches] = this._processMatches(historyItemViewModel, node.filterData);
334
414
  templateData.label.setLabel(historyItem.subject, historyItem.author, { matches, descriptionMatches, extraClasses });
335
415
  this._renderBadges(historyItem, templateData);
416
+ const actions = this._menuService.getMenuActions(MenuId.SCMHistoryItemContext, this._contextKeyService, { arg: provider, shouldForwardArgs: true });
417
+ templateData.actionBar.context = historyItem;
418
+ templateData.actionBar.setActions(getActionBarActions(actions, 'inline').primary);
419
+ }
420
+ renderCompressedElements(node, index, templateData) {
421
+ throw ( new Error('Should never happen since node is incompressible'));
336
422
  }
337
423
  _renderBadges(historyItem, templateData) {
338
424
  templateData.elementDisposables.add(autorun(reader => {
@@ -411,59 +497,6 @@ let HistoryItemRenderer = class HistoryItemRenderer {
411
497
  }))
412
498
  ];
413
499
  }
414
- _getHoverContent(element) {
415
- const colorTheme = this._themeService.getColorTheme();
416
- const historyItem = element.historyItemViewModel.historyItem;
417
- const markdown = ( new MarkdownString('', { isTrusted: true, supportThemeIcons: true }));
418
- if (historyItem.author) {
419
- const icon = URI.isUri(historyItem.authorIcon)
420
- ? `![${historyItem.author}](${( historyItem.authorIcon.toString())}|width=20,height=20)`
421
- : ThemeIcon.isThemeIcon(historyItem.authorIcon)
422
- ? `$(${historyItem.authorIcon.id})`
423
- : '$(account)';
424
- if (historyItem.authorEmail) {
425
- const emailTitle = ( localize(9221, "Email"));
426
- markdown.appendMarkdown(`${icon} [**${historyItem.author}**](mailto:${historyItem.authorEmail} "${emailTitle} ${historyItem.author}")`);
427
- }
428
- else {
429
- markdown.appendMarkdown(`${icon} **${historyItem.author}**`);
430
- }
431
- if (historyItem.timestamp) {
432
- const dateFormatter = safeIntl.DateTimeFormat(language, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' });
433
- markdown.appendMarkdown(`, $(history) ${fromNow(historyItem.timestamp, true, true)} (${dateFormatter.format(historyItem.timestamp)})`);
434
- }
435
- markdown.appendMarkdown('\n\n');
436
- }
437
- markdown.appendMarkdown(`${historyItem.message.replace(/\r\n|\r|\n/g, '\n\n')}\n\n`);
438
- if (historyItem.statistics) {
439
- markdown.appendMarkdown(`---\n\n`);
440
- markdown.appendMarkdown(`<span>${historyItem.statistics.files === 1 ?
441
- ( localize(9222, "{0} file changed", historyItem.statistics.files)) :
442
- ( localize(9223, "{0} files changed", historyItem.statistics.files))}</span>`);
443
- if (historyItem.statistics.insertions) {
444
- const additionsForegroundColor = colorTheme.getColor(historyItemHoverAdditionsForeground);
445
- markdown.appendMarkdown(`,&nbsp;<span style="color:${additionsForegroundColor};">${historyItem.statistics.insertions === 1 ?
446
- ( localize(9224, "{0} insertion{1}", historyItem.statistics.insertions, '(+)')) :
447
- ( localize(9225, "{0} insertions{1}", historyItem.statistics.insertions, '(+)'))}</span>`);
448
- }
449
- if (historyItem.statistics.deletions) {
450
- const deletionsForegroundColor = colorTheme.getColor(historyItemHoverDeletionsForeground);
451
- markdown.appendMarkdown(`,&nbsp;<span style="color:${deletionsForegroundColor};">${historyItem.statistics.deletions === 1 ?
452
- ( localize(9226, "{0} deletion{1}", historyItem.statistics.deletions, '(-)')) :
453
- ( localize(9227, "{0} deletions{1}", historyItem.statistics.deletions, '(-)'))}</span>`);
454
- }
455
- }
456
- if ((historyItem.references ?? []).length > 0) {
457
- markdown.appendMarkdown(`\n\n---\n\n`);
458
- markdown.appendMarkdown(( (historyItem.references ?? []).map(ref => {
459
- const labelIconId = ThemeIcon.isThemeIcon(ref.icon) ? ref.icon.id : '';
460
- const labelBackgroundColor = ref.color ? asCssVariable(ref.color) : asCssVariable(historyItemHoverDefaultLabelBackground);
461
- const labelForegroundColor = ref.color ? asCssVariable(historyItemHoverLabelForeground) : asCssVariable(historyItemHoverDefaultLabelForeground);
462
- return `<span style="color:${labelForegroundColor};background-color:${labelBackgroundColor};border-radius:10px;">&nbsp;$(${labelIconId})&nbsp;${ref.name}&nbsp;&nbsp;</span>`;
463
- })).join('&nbsp;&nbsp;'));
464
- }
465
- return { markdown, markdownNotSupportedFallback: historyItem.message };
466
- }
467
500
  _processMatches(historyItemViewModel, filterData) {
468
501
  if (!filterData) {
469
502
  return [undefined, undefined];
@@ -473,7 +506,7 @@ let HistoryItemRenderer = class HistoryItemRenderer {
473
506
  historyItemViewModel.historyItem.author === filterData.label ? createMatches(filterData.score) : undefined
474
507
  ];
475
508
  }
476
- disposeElement(element, index, templateData, height) {
509
+ disposeElement(element, index, templateData) {
477
510
  templateData.elementDisposables.clear();
478
511
  }
479
512
  disposeTemplate(templateData) {
@@ -482,12 +515,109 @@ let HistoryItemRenderer = class HistoryItemRenderer {
482
515
  };
483
516
  HistoryItemRenderer = HistoryItemRenderer_1 = ( __decorate([
484
517
  ( __param(1, IClipboardService)),
485
- ( __param(2, IConfigurationService)),
486
- ( __param(3, IContextKeyService)),
487
- ( __param(4, IHoverService)),
488
- ( __param(5, IMenuService)),
489
- ( __param(6, IThemeService))
518
+ ( __param(2, ICommandService)),
519
+ ( __param(3, IConfigurationService)),
520
+ ( __param(4, IContextKeyService)),
521
+ ( __param(5, IContextMenuService)),
522
+ ( __param(6, IHoverService)),
523
+ ( __param(7, IKeybindingService)),
524
+ ( __param(8, IMenuService)),
525
+ ( __param(9, ITelemetryService)),
526
+ ( __param(10, IThemeService))
490
527
  ], HistoryItemRenderer));
528
+ let HistoryItemChangeRenderer = class HistoryItemChangeRenderer {
529
+ static { HistoryItemChangeRenderer_1 = this; }
530
+ static { this.TEMPLATE_ID = 'history-item-change'; }
531
+ get templateId() { return HistoryItemChangeRenderer_1.TEMPLATE_ID; }
532
+ constructor(viewMode, resourceLabels, _commandService, _contextKeyService, _contextMenuService, _keybindingService, _labelService, _menuService, _telemetryService) {
533
+ this.viewMode = viewMode;
534
+ this.resourceLabels = resourceLabels;
535
+ this._commandService = _commandService;
536
+ this._contextKeyService = _contextKeyService;
537
+ this._contextMenuService = _contextMenuService;
538
+ this._keybindingService = _keybindingService;
539
+ this._labelService = _labelService;
540
+ this._menuService = _menuService;
541
+ this._telemetryService = _telemetryService;
542
+ }
543
+ renderTemplate(container) {
544
+ const rowElement = container.parentElement;
545
+ const element = append(container, $('.history-item-change'));
546
+ const graphPlaceholder = append(element, $('.graph-placeholder'));
547
+ const labelContainer = append(element, $('.label-container'));
548
+ const resourceLabel = this.resourceLabels.create(labelContainer, {
549
+ supportDescriptionHighlights: true, supportHighlights: true
550
+ });
551
+ const disposables = ( new DisposableStore());
552
+ const actionsContainer = append(resourceLabel.element, $('.actions'));
553
+ const actionBar = ( new WorkbenchToolBar(
554
+ actionsContainer,
555
+ undefined,
556
+ this._menuService,
557
+ this._contextKeyService,
558
+ this._contextMenuService,
559
+ this._keybindingService,
560
+ this._commandService,
561
+ this._telemetryService
562
+ ));
563
+ disposables.add(actionBar);
564
+ return { rowElement, element, graphPlaceholder, resourceLabel, actionBar, disposables };
565
+ }
566
+ renderElement(elementOrNode, index, templateData, details) {
567
+ const historyItemViewModel = isSCMHistoryItemChangeViewModelTreeElement(elementOrNode.element) ? elementOrNode.element.historyItemViewModel : elementOrNode.element.context.historyItemViewModel;
568
+ const historyItemChange = isSCMHistoryItemChangeViewModelTreeElement(elementOrNode.element) ? elementOrNode.element.historyItemChange : elementOrNode.element;
569
+ const graphColumns = isSCMHistoryItemChangeViewModelTreeElement(elementOrNode.element) ? elementOrNode.element.graphColumns : elementOrNode.element.context.historyItemViewModel.outputSwimlanes;
570
+ this._renderGraphPlaceholder(templateData, historyItemViewModel, graphColumns);
571
+ const hidePath = this.viewMode() === ViewMode.Tree;
572
+ const fileKind = isSCMHistoryItemChangeViewModelTreeElement(elementOrNode.element) ? FileKind.FILE : FileKind.FOLDER;
573
+ templateData.resourceLabel.setFile(historyItemChange.uri, { fileDecorations: { colors: false, badges: true }, fileKind, hidePath });
574
+ if (fileKind === FileKind.FILE) {
575
+ const actions = this._menuService.getMenuActions(MenuId.SCMHistoryItemChangeContext, this._contextKeyService, { arg: historyItemViewModel.historyItem, shouldForwardArgs: true });
576
+ templateData.actionBar.context = historyItemChange;
577
+ templateData.actionBar.setActions(getActionBarActions(actions, 'inline').primary);
578
+ }
579
+ else {
580
+ templateData.actionBar.context = undefined;
581
+ templateData.actionBar.setActions([]);
582
+ }
583
+ }
584
+ renderCompressedElements(node, index, templateData, details) {
585
+ const compressed = node.element;
586
+ const historyItemViewModel = compressed.elements[0].context.historyItemViewModel;
587
+ const graphColumns = compressed.elements[0].context.historyItemViewModel.outputSwimlanes;
588
+ this._renderGraphPlaceholder(templateData, historyItemViewModel, graphColumns);
589
+ const label = ( compressed.elements.map(e => e.name));
590
+ const folder = compressed.elements[compressed.elements.length - 1];
591
+ templateData.resourceLabel.setResource({ resource: folder.uri, name: label }, {
592
+ fileDecorations: { colors: false, badges: true },
593
+ fileKind: FileKind.FOLDER,
594
+ separator: this._labelService.getSeparator(folder.uri.scheme)
595
+ });
596
+ templateData.actionBar.context = undefined;
597
+ templateData.actionBar.setActions([]);
598
+ }
599
+ _renderGraphPlaceholder(templateData, historyItemViewModel, graphColumns) {
600
+ const graphPlaceholderSvgWidth = SWIMLANE_WIDTH * (graphColumns.length + 1);
601
+ const marginLeft = graphPlaceholderSvgWidth - 16 ;
602
+ templateData.rowElement.style.marginLeft = `${marginLeft}px`;
603
+ templateData.graphPlaceholder.textContent = '';
604
+ templateData.graphPlaceholder.style.left = `${ -1 * marginLeft}px`;
605
+ templateData.graphPlaceholder.style.width = `${graphPlaceholderSvgWidth}px`;
606
+ templateData.graphPlaceholder.appendChild(renderSCMHistoryGraphPlaceholder(graphColumns, getHistoryItemIndex(historyItemViewModel)));
607
+ }
608
+ disposeTemplate(templateData) {
609
+ templateData.disposables.dispose();
610
+ }
611
+ };
612
+ HistoryItemChangeRenderer = HistoryItemChangeRenderer_1 = ( __decorate([
613
+ ( __param(2, ICommandService)),
614
+ ( __param(3, IContextKeyService)),
615
+ ( __param(4, IContextMenuService)),
616
+ ( __param(5, IKeybindingService)),
617
+ ( __param(6, ILabelService)),
618
+ ( __param(7, IMenuService)),
619
+ ( __param(8, ITelemetryService))
620
+ ], HistoryItemChangeRenderer));
491
621
  let HistoryItemLoadMoreRenderer = class HistoryItemLoadMoreRenderer {
492
622
  static { HistoryItemLoadMoreRenderer_1 = this; }
493
623
  static { this.TEMPLATE_ID = 'historyItemLoadMore'; }
@@ -503,9 +633,9 @@ let HistoryItemLoadMoreRenderer = class HistoryItemLoadMoreRenderer {
503
633
  const graphPlaceholder = append(element, $('.graph-placeholder'));
504
634
  const historyItemPlaceholderContainer = append(element, $('.history-item-placeholder'));
505
635
  const historyItemPlaceholderLabel = ( new IconLabel(historyItemPlaceholderContainer, { supportIcons: true }));
506
- return { element, graphPlaceholder, historyItemPlaceholderContainer, historyItemPlaceholderLabel, elementDisposables: ( new DisposableStore()), disposables: ( new DisposableStore()) };
636
+ return { element, graphPlaceholder, historyItemPlaceholderContainer, historyItemPlaceholderLabel, elementDisposables: ( new DisposableStore()), disposables: historyItemPlaceholderLabel };
507
637
  }
508
- renderElement(element, index, templateData, height) {
638
+ renderElement(element, index, templateData) {
509
639
  templateData.graphPlaceholder.textContent = '';
510
640
  templateData.graphPlaceholder.style.width = `${SWIMLANE_WIDTH * (element.element.graphColumns.length + 1)}px`;
511
641
  templateData.graphPlaceholder.appendChild(renderSCMHistoryGraphPlaceholder(element.element.graphColumns));
@@ -519,11 +649,14 @@ let HistoryItemLoadMoreRenderer = class HistoryItemLoadMoreRenderer {
519
649
  templateData.elementDisposables.add(autorun(reader => {
520
650
  const isLoadingMore = this._isLoadingMore.read(reader);
521
651
  const icon = `$(${isLoadingMore ? 'loading~spin' : 'fold-down'})`;
522
- templateData.historyItemPlaceholderLabel.setLabel(( localize(9228, "{0} Load More...", icon)));
652
+ templateData.historyItemPlaceholderLabel.setLabel(( localize(9467, "{0} Load More...", icon)));
523
653
  }));
524
654
  }
525
655
  }
526
- disposeElement(element, index, templateData, height) {
656
+ renderCompressedElements(node, index, templateData) {
657
+ throw ( new Error('Should never happen since node is incompressible'));
658
+ }
659
+ disposeElement(element, index, templateData) {
527
660
  templateData.elementDisposables.clear();
528
661
  }
529
662
  disposeTemplate(templateData) {
@@ -573,7 +706,7 @@ SCMHistoryViewPaneActionRunner = ( __decorate([
573
706
  ], SCMHistoryViewPaneActionRunner));
574
707
  class SCMHistoryTreeAccessibilityProvider {
575
708
  getWidgetAriaLabel() {
576
- return localize(9229, "Source Control History");
709
+ return localize(9468, "Source Control History");
577
710
  }
578
711
  getAriaLabel(element) {
579
712
  if (isSCMRepository(element)) {
@@ -599,9 +732,19 @@ class SCMHistoryTreeIdentityProvider {
599
732
  const historyItem = element.historyItemViewModel.historyItem;
600
733
  return `historyItem:${provider.id}/${historyItem.id}/${historyItem.parentIds.join(',')}`;
601
734
  }
735
+ else if (isSCMHistoryItemChangeViewModelTreeElement(element)) {
736
+ const provider = element.repository.provider;
737
+ const historyItem = element.historyItemViewModel.historyItem;
738
+ return `historyItemChange:${provider.id}/${historyItem.id}/${historyItem.parentIds.join(',')}/${element.historyItemChange.uri.fsPath}`;
739
+ }
740
+ else if (isSCMHistoryItemChangeNode(element)) {
741
+ const provider = element.context.repository.provider;
742
+ const historyItem = element.context.historyItemViewModel.historyItem;
743
+ return `historyItemChangeFolder:${provider.id}/${historyItem.id}/${historyItem.parentIds.join(',')}/${element.uri.fsPath}`;
744
+ }
602
745
  else if (isSCMHistoryItemLoadMoreTreeElement(element)) {
603
746
  const provider = element.repository.provider;
604
- return `historyItemLoadMore:${provider.id}}`;
747
+ return `historyItemLoadMore:${provider.id}`;
605
748
  }
606
749
  else {
607
750
  throw ( new Error('Invalid tree element'));
@@ -623,28 +766,81 @@ class SCMHistoryTreeKeyboardNavigationLabelProvider {
623
766
  throw ( new Error('Invalid tree element'));
624
767
  }
625
768
  }
769
+ getCompressedNodeKeyboardNavigationLabel(elements) {
770
+ const folders = elements;
771
+ return ( folders.map(e => e.name)).join('/');
772
+ }
773
+ }
774
+ class SCMHistoryTreeCompressionDelegate {
775
+ isIncompressible(element) {
776
+ if (ResourceTree.isResourceNode(element)) {
777
+ return element.childrenCount === 0 || !element.parent || !element.parent.parent;
778
+ }
779
+ return true;
780
+ }
626
781
  }
627
782
  class SCMHistoryTreeDataSource extends Disposable {
783
+ constructor(viewMode) {
784
+ super();
785
+ this.viewMode = viewMode;
786
+ }
628
787
  async getChildren(inputOrElement) {
629
- if (!(inputOrElement instanceof SCMHistoryViewModel)) {
630
- return [];
631
- }
632
788
  const children = [];
633
- const historyItems = await inputOrElement.getHistoryItems();
634
- children.push(...historyItems);
635
- const repository = inputOrElement.repository.get();
636
- const lastHistoryItem = historyItems.at(-1);
637
- if (repository && lastHistoryItem && lastHistoryItem.historyItemViewModel.outputSwimlanes.length > 0) {
638
- children.push({
639
- repository,
640
- graphColumns: lastHistoryItem.historyItemViewModel.outputSwimlanes,
641
- type: 'historyItemLoadMore'
642
- });
789
+ if (inputOrElement instanceof SCMHistoryViewModel) {
790
+ const historyItems = await inputOrElement.getHistoryItems();
791
+ children.push(...historyItems);
792
+ const repository = inputOrElement.repository.get();
793
+ const lastHistoryItem = historyItems.at(-1);
794
+ if (repository && lastHistoryItem && lastHistoryItem.historyItemViewModel.outputSwimlanes.length > 0) {
795
+ children.push({
796
+ repository,
797
+ graphColumns: lastHistoryItem.historyItemViewModel.outputSwimlanes,
798
+ type: 'historyItemLoadMore'
799
+ });
800
+ }
801
+ }
802
+ else if (isSCMHistoryItemViewModelTreeElement(inputOrElement)) {
803
+ const historyItem = inputOrElement.historyItemViewModel.historyItem;
804
+ const historyItemParentId = historyItem.parentIds.length > 0 ? historyItem.parentIds[0] : undefined;
805
+ const historyProvider = inputOrElement.repository.provider.historyProvider.get();
806
+ const historyItemChanges = (await historyProvider?.provideHistoryItemChanges(historyItem.id, historyItemParentId)) ?? [];
807
+ if (this.viewMode() === ViewMode.List) {
808
+ children.push(...( historyItemChanges.map(change => ({
809
+ repository: inputOrElement.repository,
810
+ historyItemViewModel: inputOrElement.historyItemViewModel,
811
+ historyItemChange: change,
812
+ graphColumns: inputOrElement.historyItemViewModel.outputSwimlanes,
813
+ type: 'historyItemChangeViewModel'
814
+ }))));
815
+ }
816
+ else if (this.viewMode() === ViewMode.Tree) {
817
+ const rootUri = inputOrElement.repository.provider.rootUri ?? URI.file('/');
818
+ const historyItemChangesTree = ( new ResourceTree(inputOrElement, rootUri));
819
+ for (const change of historyItemChanges) {
820
+ historyItemChangesTree.add(change.uri, {
821
+ repository: inputOrElement.repository,
822
+ historyItemViewModel: inputOrElement.historyItemViewModel,
823
+ historyItemChange: change,
824
+ graphColumns: inputOrElement.historyItemViewModel.outputSwimlanes,
825
+ type: 'historyItemChangeViewModel'
826
+ });
827
+ }
828
+ for (const node of historyItemChangesTree.root.children) {
829
+ children.push(node.element ?? node);
830
+ }
831
+ }
832
+ }
833
+ else if (ResourceTree.isResourceNode(inputOrElement) && isSCMHistoryItemChangeNode(inputOrElement)) {
834
+ for (const node of inputOrElement.children) {
835
+ children.push(node.element && node.childrenCount === 0 ? node.element : node);
836
+ }
643
837
  }
644
838
  return children;
645
839
  }
646
840
  hasChildren(inputOrElement) {
647
- return inputOrElement instanceof SCMHistoryViewModel;
841
+ return inputOrElement instanceof SCMHistoryViewModel ||
842
+ isSCMHistoryItemViewModelTreeElement(inputOrElement) ||
843
+ (isSCMHistoryItemChangeNode(inputOrElement) && inputOrElement.childrenCount > 0);
648
844
  }
649
845
  }
650
846
  let SCMHistoryViewModel = class SCMHistoryViewModel extends Disposable {
@@ -662,9 +858,12 @@ let SCMHistoryViewModel = class SCMHistoryViewModel extends Disposable {
662
858
  this._repositoryState = ( new Map());
663
859
  this._repositoryFilterState = ( new Map());
664
860
  this._repositoryFilterState = this._loadHistoryItemsFilterState();
861
+ this.viewMode = observableValue(this, this._getViewMode());
665
862
  this._extensionService.onWillStop(this._saveHistoryItemsFilterState, this, this._store);
666
863
  this._storageService.onWillSaveState(this._saveHistoryItemsFilterState, this, this._store);
667
864
  this._scmHistoryItemCountCtx = ContextKeys.SCMHistoryItemCount.bindTo(this._contextKeyService);
865
+ this._scmHistoryViewModeCtx = ContextKeys.SCMHistoryViewMode.bindTo(this._contextKeyService);
866
+ this._scmHistoryViewModeCtx.set(this.viewMode.get());
668
867
  const firstRepository = this._scmService.repositoryCount > 0
669
868
  ? constObservable(Iterable.first(this._scmService.repositories))
670
869
  : observableFromEvent(this, Event.once(this._scmService.onDidAddRepository), repository => repository);
@@ -784,6 +983,22 @@ let SCMHistoryViewModel = class SCMHistoryViewModel extends Disposable {
784
983
  this._saveHistoryItemsFilterState();
785
984
  this.onDidChangeHistoryItemsFilter.trigger(undefined);
786
985
  }
986
+ setViewMode(viewMode) {
987
+ if (viewMode === this.viewMode.get()) {
988
+ return;
989
+ }
990
+ this.viewMode.set(viewMode, undefined);
991
+ this._scmHistoryViewModeCtx.set(viewMode);
992
+ this._storageService.store('scm.graphView.viewMode', viewMode, StorageScope.WORKSPACE, StorageTarget.USER);
993
+ }
994
+ _getViewMode() {
995
+ let mode = this._configurationService.getValue('scm.defaultViewMode') === 'list' ? ViewMode.List : ViewMode.Tree;
996
+ const storageMode = this._storageService.get('scm.graphView.viewMode', StorageScope.WORKSPACE);
997
+ if (typeof storageMode === 'string') {
998
+ mode = storageMode;
999
+ }
1000
+ return mode;
1001
+ }
787
1002
  _getGraphColorMap(historyItemRefs) {
788
1003
  const repository = this.repository.get();
789
1004
  const historyProvider = repository?.provider.historyProvider.get();
@@ -874,8 +1089,8 @@ let RepositoryPicker = class RepositoryPicker {
874
1089
  this._quickInputService = _quickInputService;
875
1090
  this._scmViewService = _scmViewService;
876
1091
  this._autoQuickPickItem = {
877
- label: ( localize(9212, "Auto")),
878
- description: ( localize(9230, "Show the source control graph for the active repository")),
1092
+ label: ( localize(9455, "Auto")),
1093
+ description: ( localize(9469, "Show the source control graph for the active repository")),
879
1094
  repository: 'auto'
880
1095
  };
881
1096
  }
@@ -891,7 +1106,7 @@ let RepositoryPicker = class RepositoryPicker {
891
1106
  repository: r
892
1107
  }))));
893
1108
  return this._quickInputService.pick(picks, {
894
- placeHolder: ( localize(9231, "Select the repository to view, type to filter all repositories"))
1109
+ placeHolder: ( localize(9470, "Select the repository to view, type to filter all repositories"))
895
1110
  });
896
1111
  }
897
1112
  };
@@ -907,21 +1122,21 @@ let HistoryItemRefPicker = class HistoryItemRefPicker extends Disposable {
907
1122
  this._quickInputService = _quickInputService;
908
1123
  this._allQuickPickItem = {
909
1124
  id: 'all',
910
- label: ( localize(9211, "All")),
911
- description: ( localize(9214, "All history item references")),
1125
+ label: ( localize(9454, "All")),
1126
+ description: ( localize(9457, "All history item references")),
912
1127
  historyItemRef: 'all'
913
1128
  };
914
1129
  this._autoQuickPickItem = {
915
1130
  id: 'auto',
916
- label: ( localize(9212, "Auto")),
917
- description: ( localize(9232, "Current history item reference(s)")),
1131
+ label: ( localize(9455, "Auto")),
1132
+ description: ( localize(9471, "Current history item reference(s)")),
918
1133
  historyItemRef: 'auto'
919
1134
  };
920
1135
  }
921
1136
  async pickHistoryItemRef() {
922
1137
  const quickPick = this._quickInputService.createQuickPick({ useSeparators: true });
923
1138
  this._store.add(quickPick);
924
- quickPick.placeholder = ( localize(9233, "Select one/more history item references to view, type to filter"));
1139
+ quickPick.placeholder = ( localize(9472, "Select one/more history item references to view, type to filter"));
925
1140
  quickPick.canSelectMany = true;
926
1141
  quickPick.hideCheckAll = true;
927
1142
  quickPick.busy = true;
@@ -1018,13 +1233,13 @@ HistoryItemRefPicker = ( __decorate([
1018
1233
  ( __param(2, IQuickInputService))
1019
1234
  ], HistoryItemRefPicker));
1020
1235
  let SCMHistoryViewPane = class SCMHistoryViewPane extends ViewPane {
1021
- constructor(options, _commandService, _instantiationService, _menuService, _progressService, configurationService, contextMenuService, keybindingService, instantiationService, viewDescriptorService, contextKeyService, openerService, themeService, hoverService) {
1236
+ constructor(options, _editorService, _instantiationService, _menuService, _progressService, configurationService, contextMenuService, keybindingService, instantiationService, viewDescriptorService, contextKeyService, openerService, themeService, hoverService) {
1022
1237
  super({
1023
1238
  ...options,
1024
1239
  titleMenuId: MenuId.SCMHistoryTitle,
1025
1240
  showActions: ViewPaneShowActions.WhenExpanded
1026
1241
  }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, hoverService);
1027
- this._commandService = _commandService;
1242
+ this._editorService = _editorService;
1028
1243
  this._instantiationService = _instantiationService;
1029
1244
  this._menuService = _menuService;
1030
1245
  this._progressService = _progressService;
@@ -1051,7 +1266,7 @@ let SCMHistoryViewPane = class SCMHistoryViewPane extends ViewPane {
1051
1266
  container.appendChild(element.root);
1052
1267
  this._register(this.hoverService.setupManagedHover(getDefaultHoverDelegate('mouse'), element.root, {
1053
1268
  markdown: {
1054
- value: ( localize(9234, "Please refresh the graph using the refresh action ($(refresh)).")),
1269
+ value: ( localize(9473, "Please refresh the graph using the refresh action ($(refresh)).")),
1055
1270
  supportThemeIcons: true
1056
1271
  },
1057
1272
  markdownNotSupportedFallback: undefined
@@ -1063,7 +1278,7 @@ let SCMHistoryViewPane = class SCMHistoryViewPane extends ViewPane {
1063
1278
  }
1064
1279
  renderBody(container) {
1065
1280
  super.renderBody(container);
1066
- this._treeContainer = append(container, $('.scm-view.scm-history-view'));
1281
+ this._treeContainer = append(container, $('.scm-view.scm-history-view.show-file-icons'));
1067
1282
  this._treeContainer.classList.add('file-icon-themable-tree');
1068
1283
  this._createTree(this._treeContainer);
1069
1284
  this.onDidChangeBodyVisibility(async (visible) => {
@@ -1122,6 +1337,9 @@ let SCMHistoryViewPane = class SCMHistoryViewPane extends ViewPane {
1122
1337
  store.add(autorun(reader => {
1123
1338
  this._scmCurrentHistoryItemRefHasRemote.set(!!historyProvider.historyItemRemoteRef.read(reader));
1124
1339
  }));
1340
+ store.add(runOnChange(this._treeViewModel.viewMode, async () => {
1341
+ await this._updateChildren();
1342
+ }));
1125
1343
  this._scmProviderCtx.set(repository.provider.contextValue);
1126
1344
  this._scmCurrentHistoryItemRefInFilter.set(this._isCurrentHistoryItemInFilter(historyItemRefId.get()));
1127
1345
  if (!isFirstRun) {
@@ -1129,6 +1347,12 @@ let SCMHistoryViewPane = class SCMHistoryViewPane extends ViewPane {
1129
1347
  }
1130
1348
  isFirstRun = false;
1131
1349
  }));
1350
+ const fileIconThemeObs = observableFromEvent(this.themeService.onDidFileIconThemeChange, () => this.themeService.getFileIconTheme());
1351
+ this._visibilityDisposables.add(autorun(reader => {
1352
+ const fileIconTheme = fileIconThemeObs.read(reader);
1353
+ const viewMode = this._treeViewModel.viewMode.read(reader);
1354
+ this._updateIndentStyles(fileIconTheme, viewMode);
1355
+ }));
1132
1356
  }, this, this._store);
1133
1357
  }
1134
1358
  layoutBody(height, width) {
@@ -1219,22 +1443,30 @@ let SCMHistoryViewPane = class SCMHistoryViewPane extends ViewPane {
1219
1443
  await this._loadMore(historyItemRef.revision);
1220
1444
  revealTreeNode();
1221
1445
  }
1446
+ setViewMode(viewMode) {
1447
+ this._treeViewModel.setViewMode(viewMode);
1448
+ }
1222
1449
  _createTree(container) {
1223
1450
  this._treeIdentityProvider = ( new SCMHistoryTreeIdentityProvider());
1224
1451
  const historyItemHoverDelegate = this.instantiationService.createInstance(HistoryItemHoverDelegate, this.viewDescriptorService.getViewLocationById(this.id));
1225
1452
  this._register(historyItemHoverDelegate);
1226
- this._treeDataSource = this.instantiationService.createInstance(SCMHistoryTreeDataSource);
1453
+ const resourceLabels = this.instantiationService.createInstance(ResourceLabels, { onDidChangeVisibility: this.onDidChangeBodyVisibility });
1454
+ this._register(resourceLabels);
1455
+ this._treeDataSource = this.instantiationService.createInstance(SCMHistoryTreeDataSource, () => this._treeViewModel.viewMode.get());
1227
1456
  this._register(this._treeDataSource);
1228
- this._tree = this.instantiationService.createInstance(WorkbenchAsyncDataTree, 'SCM History Tree', container, ( new ListDelegate()), [
1457
+ const compressionEnabled = observableConfigValue('scm.compactFolders', true, this.configurationService);
1458
+ this._tree = this.instantiationService.createInstance(WorkbenchCompressibleAsyncDataTree, 'SCM History Tree', container, ( new ListDelegate()), ( new SCMHistoryTreeCompressionDelegate()), [
1229
1459
  this.instantiationService.createInstance(HistoryItemRenderer, historyItemHoverDelegate),
1460
+ this.instantiationService.createInstance(HistoryItemChangeRenderer, () => this._treeViewModel.viewMode.get(), resourceLabels),
1230
1461
  this.instantiationService.createInstance(HistoryItemLoadMoreRenderer, this._repositoryIsLoadingMore, () => this._loadMore()),
1231
1462
  ], this._treeDataSource, {
1232
1463
  accessibilityProvider: ( new SCMHistoryTreeAccessibilityProvider()),
1233
1464
  identityProvider: this._treeIdentityProvider,
1234
- collapseByDefault: (e) => false,
1465
+ collapseByDefault: (e) => !isSCMHistoryItemChangeNode(e),
1466
+ compressionEnabled: compressionEnabled.get(),
1235
1467
  keyboardNavigationLabelProvider: ( new SCMHistoryTreeKeyboardNavigationLabelProvider()),
1236
1468
  horizontalScrolling: false,
1237
- multipleSelectionSupport: false,
1469
+ multipleSelectionSupport: false
1238
1470
  });
1239
1471
  this._register(this._tree);
1240
1472
  this._tree.onDidOpen(this._onDidOpen, this, this._store);
@@ -1254,20 +1486,38 @@ let SCMHistoryViewPane = class SCMHistoryViewPane extends ViewPane {
1254
1486
  if (!e.element) {
1255
1487
  return;
1256
1488
  }
1257
- else if (isSCMHistoryItemViewModelTreeElement(e.element)) {
1489
+ else if (isSCMHistoryItemChangeViewModelTreeElement(e.element)) {
1490
+ const historyItemChange = e.element.historyItemChange;
1258
1491
  const historyItem = e.element.historyItemViewModel.historyItem;
1492
+ const historyItemDisplayId = historyItem.displayId ?? historyItem.id;
1259
1493
  const historyItemParentId = historyItem.parentIds.length > 0 ? historyItem.parentIds[0] : undefined;
1260
- const historyProvider = e.element.repository.provider.historyProvider.get();
1261
- const historyItemChanges = await historyProvider?.provideHistoryItemChanges(historyItem.id, historyItemParentId);
1262
- if (historyItemChanges) {
1263
- const title = getHistoryItemEditorTitle(historyItem);
1264
- const rootUri = e.element.repository.provider.rootUri;
1265
- const path = rootUri ? rootUri.path : e.element.repository.provider.label;
1266
- const multiDiffSourceUri = ( URI.from(
1267
- { scheme: 'scm-history-item', path: `${path}/${historyItemParentId}..${historyItem.id}` },
1268
- true
1269
- ));
1270
- await this._commandService.executeCommand('_workbench.openMultiDiffEditor', { title, multiDiffSourceUri, resources: historyItemChanges });
1494
+ const historyItemParentDisplayId = historyItemParentId && historyItem.displayId
1495
+ ? historyItemParentId.substring(0, historyItem.displayId.length)
1496
+ : historyItemParentId;
1497
+ if (historyItemChange.originalUri && historyItemChange.modifiedUri) {
1498
+ const originalUriTitle = `${basename(historyItemChange.originalUri.fsPath)} (${historyItemParentDisplayId})`;
1499
+ const modifiedUriTitle = `${basename(historyItemChange.modifiedUri.fsPath)} (${historyItemDisplayId})`;
1500
+ const title = `${originalUriTitle} ↔ ${modifiedUriTitle}`;
1501
+ await this._editorService.openEditor({
1502
+ label: title,
1503
+ original: { resource: historyItemChange.originalUri },
1504
+ modified: { resource: historyItemChange.modifiedUri },
1505
+ options: e.editorOptions
1506
+ });
1507
+ }
1508
+ else if (historyItemChange.modifiedUri) {
1509
+ await this._editorService.openEditor({
1510
+ label: `${basename(historyItemChange.modifiedUri.fsPath)} (${historyItemDisplayId})`,
1511
+ resource: historyItemChange.modifiedUri,
1512
+ options: e.editorOptions
1513
+ });
1514
+ }
1515
+ else if (historyItemChange.originalUri) {
1516
+ await this._editorService.openEditor({
1517
+ label: `${basename(historyItemChange.originalUri.fsPath)} (${historyItemParentDisplayId})`,
1518
+ resource: historyItemChange.originalUri,
1519
+ options: e.editorOptions
1520
+ });
1271
1521
  }
1272
1522
  }
1273
1523
  else if (isSCMHistoryItemLoadMoreTreeElement(e.element)) {
@@ -1333,7 +1583,7 @@ let SCMHistoryViewPane = class SCMHistoryViewPane extends ViewPane {
1333
1583
  const historyItemMenuActions = this._menuService.getMenuActions(MenuId.SCMHistoryItemContext, this.scopedContextKeyService, {
1334
1584
  arg: element.repository.provider,
1335
1585
  shouldForwardArgs: true
1336
- });
1586
+ }).filter(group => group[0] !== 'inline');
1337
1587
  this.contextMenuService.showContextMenu({
1338
1588
  contextKeyService: this.scopedContextKeyService,
1339
1589
  getAnchor: () => e.anchor,
@@ -1354,12 +1604,18 @@ let SCMHistoryViewPane = class SCMHistoryViewPane extends ViewPane {
1354
1604
  }
1355
1605
  _updateChildren() {
1356
1606
  return this._updateChildrenThrottler.queue(() => this._treeOperationSequencer.queue(async () => {
1357
- await this._progressService.withProgress({ location: this.id }, async () => {
1607
+ await this._progressService.withProgress({ location: this.id, delay: 100 }, async () => {
1358
1608
  await this._tree.updateChildren(undefined, undefined, undefined, {
1359
1609
  });
1360
1610
  });
1361
1611
  }));
1362
1612
  }
1613
+ _updateIndentStyles(theme, viewMode) {
1614
+ this._treeContainer.classList.toggle('list-view-mode', viewMode === ViewMode.List);
1615
+ this._treeContainer.classList.toggle('tree-view-mode', viewMode === ViewMode.Tree);
1616
+ this._treeContainer.classList.toggle('align-icons-and-twisties', (viewMode === ViewMode.List && theme.hasFileIcons) || (theme.hasFileIcons && !theme.hasFolderIcons));
1617
+ this._treeContainer.classList.toggle('hide-arrows', viewMode === ViewMode.Tree && theme.hidesExplorerArrows === true);
1618
+ }
1363
1619
  dispose() {
1364
1620
  this._contextMenuDisposables.dispose();
1365
1621
  this._visibilityDisposables.dispose();
@@ -1367,7 +1623,7 @@ let SCMHistoryViewPane = class SCMHistoryViewPane extends ViewPane {
1367
1623
  }
1368
1624
  };
1369
1625
  SCMHistoryViewPane = ( __decorate([
1370
- ( __param(1, ICommandService)),
1626
+ ( __param(1, IEditorService)),
1371
1627
  ( __param(2, IInstantiationService)),
1372
1628
  ( __param(3, IMenuService)),
1373
1629
  ( __param(4, IProgressService)),