@codingame/monaco-vscode-timeline-service-override 3.2.3 → 4.1.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.
@@ -1,1163 +0,0 @@
1
- import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
2
- import './media/timelinePane.css.js';
3
- import { localize2WithPath, localizeWithPath } from 'vscode/vscode/vs/nls';
4
- import { clearNode, append, $, asCSSUrl } from 'vscode/vscode/vs/base/browser/dom';
5
- import { ActionRunner } from 'vscode/vscode/vs/base/common/actions';
6
- import { CancellationTokenSource } from 'vscode/vscode/vs/base/common/cancellation';
7
- import { fromNow } from 'vscode/vscode/vs/base/common/date';
8
- import { debounce } from 'vscode/vscode/vs/base/common/decorators';
9
- import { Emitter } from 'vscode/vscode/vs/base/common/event';
10
- import { createMatches } from 'vscode/vscode/vs/base/common/filters';
11
- import { Iterable } from 'vscode/vscode/vs/base/common/iterator';
12
- import { DisposableStore, Disposable } from 'vscode/vscode/vs/base/common/lifecycle';
13
- import { Schemas } from 'vscode/vscode/vs/base/common/network';
14
- import { ILabelService } from 'vscode/vscode/vs/platform/label/common/label';
15
- import { escapeRegExpCharacters } from 'vscode/vscode/vs/base/common/strings';
16
- import { URI } from 'vscode/vscode/vs/base/common/uri';
17
- import { IconLabel } from 'vscode/vscode/vs/base/browser/ui/iconLabel/iconLabel';
18
- import { ViewPane } from 'vscode/vscode/vs/workbench/browser/parts/views/viewPane';
19
- import { WorkbenchObjectTree } from 'vscode/vscode/vs/platform/list/browser/listService';
20
- import { IKeybindingService } from 'vscode/vscode/vs/platform/keybinding/common/keybinding';
21
- import { IContextMenuService } from 'vscode/vscode/vs/platform/contextview/browser/contextView';
22
- import { RawContextKey, ContextKeyExpr, IContextKeyService } from 'vscode/vscode/vs/platform/contextkey/common/contextkey';
23
- import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration';
24
- import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
25
- import { ITimelineService } from 'vscode/vscode/vs/workbench/contrib/timeline/common/timeline';
26
- import { IEditorService } from 'vscode/vscode/vs/workbench/services/editor/common/editorService';
27
- import { EditorResourceAccessor, SideBySideEditor } from 'vscode/vscode/vs/workbench/common/editor';
28
- import { CommandsRegistry, ICommandService } from 'vscode/vscode/vs/platform/commands/common/commands';
29
- import { IThemeService } from 'vscode/vscode/vs/platform/theme/common/themeService';
30
- import { ThemeIcon } from 'vscode/vscode/vs/base/common/themables';
31
- import { IViewDescriptorService } from 'vscode/vscode/vs/workbench/common/views';
32
- import { IProgressService } from 'vscode/vscode/vs/platform/progress/common/progress';
33
- import { IOpenerService } from 'vscode/vscode/vs/platform/opener/common/opener';
34
- import { ActionBar } from 'vscode/vscode/vs/base/browser/ui/actionbar/actionbar';
35
- import { createActionViewItem, createAndFillInContextMenuActions } from 'vscode/vscode/vs/platform/actions/browser/menuEntryActionViewItem';
36
- import { MenuId, registerAction2, Action2, MenuRegistry, IMenuService } from 'vscode/vscode/vs/platform/actions/common/actions';
37
- import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry';
38
- import { ActionViewItem } from 'vscode/vscode/vs/base/browser/ui/actionbar/actionViewItems';
39
- import { ColorScheme } from 'vscode/vscode/vs/platform/theme/common/theme';
40
- import { Codicon } from 'vscode/vscode/vs/base/common/codicons';
41
- import { registerIcon } from 'vscode/vscode/vs/platform/theme/common/iconRegistry';
42
- import { API_OPEN_EDITOR_COMMAND_ID, API_OPEN_DIFF_EDITOR_COMMAND_ID } from 'vscode/vscode/vs/workbench/browser/parts/editor/editorCommands';
43
- import { isString } from 'vscode/vscode/vs/base/common/types';
44
- import { renderMarkdownAsPlaintext } from 'vscode/vscode/vs/base/browser/markdownRenderer';
45
- import { IUriIdentityService } from 'vscode/vscode/vs/platform/uriIdentity/common/uriIdentity';
46
- import { IExtensionService } from 'vscode/vscode/vs/workbench/services/extensions/common/extensions';
47
- import { IStorageService } from 'vscode/vscode/vs/platform/storage/common/storage';
48
- import { getDefaultHoverDelegate } from 'vscode/vscode/vs/base/browser/ui/hover/hoverDelegate';
49
-
50
- const ItemHeight = 22;
51
- function isLoadMoreCommand(item) {
52
- return item instanceof LoadMoreCommand;
53
- }
54
- function isTimelineItem(item) {
55
- return !item?.handle.startsWith('vscode-command:') ?? false;
56
- }
57
- function updateRelativeTime(item, lastRelativeTime) {
58
- item.relativeTime = isTimelineItem(item) ? fromNow(item.timestamp) : undefined;
59
- item.relativeTimeFullWord = isTimelineItem(item) ? fromNow(item.timestamp, false, true) : undefined;
60
- if (lastRelativeTime === undefined || item.relativeTime !== lastRelativeTime) {
61
- lastRelativeTime = item.relativeTime;
62
- item.hideRelativeTime = false;
63
- }
64
- else {
65
- item.hideRelativeTime = true;
66
- }
67
- return lastRelativeTime;
68
- }
69
- class TimelineAggregate {
70
- constructor(timeline) {
71
- this._stale = false;
72
- this._requiresReset = false;
73
- this.source = timeline.source;
74
- this.items = timeline.items;
75
- this._cursor = timeline.paging?.cursor;
76
- this.lastRenderedIndex = -1;
77
- }
78
- get cursor() {
79
- return this._cursor;
80
- }
81
- get more() {
82
- return this._cursor !== undefined;
83
- }
84
- get newest() {
85
- return this.items[0];
86
- }
87
- get oldest() {
88
- return this.items[this.items.length - 1];
89
- }
90
- add(timeline, options) {
91
- let updated = false;
92
- if (timeline.items.length !== 0 && this.items.length !== 0) {
93
- updated = true;
94
- const ids = ( new Set());
95
- const timestamps = ( new Set());
96
- for (const item of timeline.items) {
97
- if (item.id === undefined) {
98
- timestamps.add(item.timestamp);
99
- }
100
- else {
101
- ids.add(item.id);
102
- }
103
- }
104
- let i = this.items.length;
105
- let item;
106
- while (i--) {
107
- item = this.items[i];
108
- if ((item.id !== undefined && ( ids.has(item.id))) || ( timestamps.has(item.timestamp))) {
109
- this.items.splice(i, 1);
110
- }
111
- }
112
- if ((timeline.items[timeline.items.length - 1]?.timestamp ?? 0) >= (this.newest?.timestamp ?? 0)) {
113
- this.items.splice(0, 0, ...timeline.items);
114
- }
115
- else {
116
- this.items.push(...timeline.items);
117
- }
118
- }
119
- else if (timeline.items.length !== 0) {
120
- updated = true;
121
- this.items.push(...timeline.items);
122
- }
123
- if (options.cursor !== undefined || typeof options.limit !== 'object') {
124
- this._cursor = timeline.paging?.cursor;
125
- }
126
- if (updated) {
127
- this.items.sort((a, b) => (b.timestamp - a.timestamp) ||
128
- (a.source === undefined
129
- ? b.source === undefined ? 0 : 1
130
- : b.source === undefined ? -1 : b.source.localeCompare(a.source, undefined, { numeric: true, sensitivity: 'base' })));
131
- }
132
- return updated;
133
- }
134
- get stale() {
135
- return this._stale;
136
- }
137
- get requiresReset() {
138
- return this._requiresReset;
139
- }
140
- invalidate(requiresReset) {
141
- this._stale = true;
142
- this._requiresReset = requiresReset;
143
- }
144
- }
145
- class LoadMoreCommand {
146
- constructor(loading) {
147
- this.handle = 'vscode-command:loadMore';
148
- this.timestamp = 0;
149
- this.description = undefined;
150
- this.tooltip = undefined;
151
- this.contextValue = undefined;
152
- this.id = undefined;
153
- this.icon = undefined;
154
- this.iconDark = undefined;
155
- this.source = undefined;
156
- this.relativeTime = undefined;
157
- this.relativeTimeFullWord = undefined;
158
- this.hideRelativeTime = undefined;
159
- this._loading = false;
160
- this._loading = loading;
161
- }
162
- get loading() {
163
- return this._loading;
164
- }
165
- set loading(value) {
166
- this._loading = value;
167
- }
168
- get ariaLabel() {
169
- return this.label;
170
- }
171
- get label() {
172
- return this.loading ? ( localizeWithPath(
173
- 'vs/workbench/contrib/timeline/browser/timelinePane',
174
- 'timeline.loadingMore',
175
- "Loading..."
176
- )) : ( localizeWithPath(
177
- 'vs/workbench/contrib/timeline/browser/timelinePane',
178
- 'timeline.loadMore',
179
- "Load more"
180
- ));
181
- }
182
- get themeIcon() {
183
- return undefined;
184
- }
185
- }
186
- const TimelineFollowActiveEditorContext = ( new RawContextKey('timelineFollowActiveEditor', true, true));
187
- const TimelineExcludeSources = ( new RawContextKey('timelineExcludeSources', '[]', true));
188
- let TimelinePane = class TimelinePane extends ViewPane {
189
- static { this.TITLE = ( localize2WithPath(
190
- 'vs/workbench/contrib/timeline/browser/timelinePane',
191
- 'timeline',
192
- "Timeline"
193
- )); }
194
- constructor(options, keybindingService, contextMenuService, contextKeyService, configurationService, storageService, viewDescriptorService, instantiationService, editorService, commandService, progressService, timelineService, openerService, themeService, telemetryService, labelService, uriIdentityService, extensionService) {
195
- super({ ...options, titleMenuId: MenuId.TimelineTitle }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
196
- this.storageService = storageService;
197
- this.editorService = editorService;
198
- this.commandService = commandService;
199
- this.progressService = progressService;
200
- this.timelineService = timelineService;
201
- this.labelService = labelService;
202
- this.uriIdentityService = uriIdentityService;
203
- this.extensionService = extensionService;
204
- this.pendingRequests = ( new Map());
205
- this.timelinesBySource = ( new Map());
206
- this._followActiveEditor = true;
207
- this._isEmpty = true;
208
- this._maxItemCount = 0;
209
- this._visibleItemCount = 0;
210
- this._pendingRefresh = false;
211
- this.commands = this._register(this.instantiationService.createInstance(TimelinePaneCommands, this));
212
- this.followActiveEditorContext = TimelineFollowActiveEditorContext.bindTo(this.contextKeyService);
213
- this.timelineExcludeSourcesContext = TimelineExcludeSources.bindTo(this.contextKeyService);
214
- const excludedSourcesString = storageService.get('timeline.excludeSources', 0 , '[]');
215
- this.timelineExcludeSourcesContext.set(excludedSourcesString);
216
- this.excludedSources = ( new Set(JSON.parse(excludedSourcesString)));
217
- this._register(storageService.onDidChangeValue(0 , 'timeline.excludeSources', this._register(( new DisposableStore())))(this.onStorageServiceChanged, this));
218
- this._register(configurationService.onDidChangeConfiguration(this.onConfigurationChanged, this));
219
- this._register(timelineService.onDidChangeProviders(this.onProvidersChanged, this));
220
- this._register(timelineService.onDidChangeTimeline(this.onTimelineChanged, this));
221
- this._register(timelineService.onDidChangeUri(uri => this.setUri(uri), this));
222
- }
223
- get followActiveEditor() {
224
- return this._followActiveEditor;
225
- }
226
- set followActiveEditor(value) {
227
- if (this._followActiveEditor === value) {
228
- return;
229
- }
230
- this._followActiveEditor = value;
231
- this.followActiveEditorContext.set(value);
232
- this.updateFilename(this._filename);
233
- if (value) {
234
- this.onActiveEditorChanged();
235
- }
236
- }
237
- get pageOnScroll() {
238
- if (this._pageOnScroll === undefined) {
239
- this._pageOnScroll = this.configurationService.getValue('timeline.pageOnScroll') ?? false;
240
- }
241
- return this._pageOnScroll;
242
- }
243
- get pageSize() {
244
- let pageSize = this.configurationService.getValue('timeline.pageSize');
245
- if (pageSize === undefined || pageSize === null) {
246
- pageSize = Math.max(20, Math.floor((this.tree?.renderHeight ?? 0 / ItemHeight) + (this.pageOnScroll ? 1 : -1)));
247
- }
248
- return pageSize;
249
- }
250
- reset() {
251
- this.loadTimeline(true);
252
- }
253
- setUri(uri) {
254
- this.setUriCore(uri, true);
255
- }
256
- setUriCore(uri, disableFollowing) {
257
- if (disableFollowing) {
258
- this.followActiveEditor = false;
259
- }
260
- this.uri = uri;
261
- this.updateFilename(uri ? this.labelService.getUriBasenameLabel(uri) : undefined);
262
- this.treeRenderer?.setUri(uri);
263
- this.loadTimeline(true);
264
- }
265
- onStorageServiceChanged() {
266
- const excludedSourcesString = this.storageService.get('timeline.excludeSources', 0 , '[]');
267
- this.timelineExcludeSourcesContext.set(excludedSourcesString);
268
- this.excludedSources = ( new Set(JSON.parse(excludedSourcesString)));
269
- const missing = this.timelineService.getSources()
270
- .filter(({ id }) => !( this.excludedSources.has(id)) && !( this.timelinesBySource.has(id)));
271
- if (missing.length !== 0) {
272
- this.loadTimeline(true, ( missing.map(({ id }) => id)));
273
- }
274
- else {
275
- this.refresh();
276
- }
277
- }
278
- onConfigurationChanged(e) {
279
- if (e.affectsConfiguration('timeline.pageOnScroll')) {
280
- this._pageOnScroll = undefined;
281
- }
282
- }
283
- onActiveEditorChanged() {
284
- if (!this.followActiveEditor || !this.isExpanded()) {
285
- return;
286
- }
287
- const uri = EditorResourceAccessor.getOriginalUri(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY });
288
- if ((this.uriIdentityService.extUri.isEqual(uri, this.uri) && uri !== undefined) ||
289
- (uri?.fsPath === this.uri?.fsPath && (uri?.scheme === Schemas.file || uri?.scheme === 'git') && (this.uri?.scheme === Schemas.file || this.uri?.scheme === 'git'))) {
290
- for (const source of this.timelineService.getSources()) {
291
- if (( this.excludedSources.has(source.id))) {
292
- continue;
293
- }
294
- const timeline = this.timelinesBySource.get(source.id);
295
- if (timeline !== undefined && !timeline.stale) {
296
- continue;
297
- }
298
- if (timeline !== undefined) {
299
- this.updateTimeline(timeline, timeline.requiresReset);
300
- }
301
- else {
302
- this.loadTimelineForSource(source.id, uri, true);
303
- }
304
- }
305
- return;
306
- }
307
- this.setUriCore(uri, false);
308
- }
309
- onProvidersChanged(e) {
310
- if (e.removed) {
311
- for (const source of e.removed) {
312
- this.timelinesBySource.delete(source);
313
- }
314
- this.refresh();
315
- }
316
- if (e.added) {
317
- this.loadTimeline(true, e.added);
318
- }
319
- }
320
- onTimelineChanged(e) {
321
- if (e?.uri === undefined || this.uriIdentityService.extUri.isEqual(e.uri, this.uri)) {
322
- const timeline = this.timelinesBySource.get(e.id);
323
- if (timeline === undefined) {
324
- return;
325
- }
326
- if (this.isBodyVisible()) {
327
- this.updateTimeline(timeline, e.reset);
328
- }
329
- else {
330
- timeline.invalidate(e.reset);
331
- }
332
- }
333
- }
334
- updateFilename(filename) {
335
- this._filename = filename;
336
- if (this.followActiveEditor || !filename) {
337
- this.updateTitleDescription(filename);
338
- }
339
- else {
340
- this.updateTitleDescription(`${filename} (pinned)`);
341
- }
342
- }
343
- get message() {
344
- return this._message;
345
- }
346
- set message(message) {
347
- this._message = message;
348
- this.updateMessage();
349
- }
350
- updateMessage() {
351
- if (this._message !== undefined) {
352
- this.showMessage(this._message);
353
- }
354
- else {
355
- this.hideMessage();
356
- }
357
- }
358
- showMessage(message) {
359
- if (!this.$message) {
360
- return;
361
- }
362
- this.$message.classList.remove('hide');
363
- this.resetMessageElement();
364
- this.$message.textContent = message;
365
- }
366
- hideMessage() {
367
- this.resetMessageElement();
368
- this.$message.classList.add('hide');
369
- }
370
- resetMessageElement() {
371
- clearNode(this.$message);
372
- }
373
- get hasVisibleItems() {
374
- return this._visibleItemCount > 0;
375
- }
376
- clear(cancelPending) {
377
- this._visibleItemCount = 0;
378
- this._maxItemCount = this.pageSize;
379
- this.timelinesBySource.clear();
380
- if (cancelPending) {
381
- for (const { tokenSource } of ( this.pendingRequests.values())) {
382
- tokenSource.dispose(true);
383
- }
384
- this.pendingRequests.clear();
385
- if (!this.isBodyVisible() && this.tree) {
386
- this.tree.setChildren(null, undefined);
387
- this._isEmpty = true;
388
- }
389
- }
390
- }
391
- async loadTimeline(reset, sources) {
392
- if (sources === undefined) {
393
- if (reset) {
394
- this.clear(true);
395
- }
396
- if (this.uri?.scheme === Schemas.vscodeSettings || this.uri?.scheme === Schemas.webviewPanel || this.uri?.scheme === Schemas.walkThrough) {
397
- this.uri = undefined;
398
- this.clear(false);
399
- this.refresh();
400
- return;
401
- }
402
- if (this._isEmpty && this.uri !== undefined) {
403
- this.setLoadingUriMessage();
404
- }
405
- }
406
- if (this.uri === undefined) {
407
- this.clear(false);
408
- this.refresh();
409
- return;
410
- }
411
- if (!this.isBodyVisible()) {
412
- return;
413
- }
414
- let hasPendingRequests = false;
415
- for (const source of sources ?? ( this.timelineService.getSources().map(s => s.id))) {
416
- const requested = this.loadTimelineForSource(source, this.uri, reset);
417
- if (requested) {
418
- hasPendingRequests = true;
419
- }
420
- }
421
- if (!hasPendingRequests) {
422
- this.refresh();
423
- }
424
- else if (this._isEmpty) {
425
- this.setLoadingUriMessage();
426
- }
427
- }
428
- loadTimelineForSource(source, uri, reset, options) {
429
- if (( this.excludedSources.has(source))) {
430
- return false;
431
- }
432
- const timeline = this.timelinesBySource.get(source);
433
- if (!reset &&
434
- options?.cursor !== undefined &&
435
- timeline !== undefined &&
436
- (!timeline?.more || timeline.items.length > timeline.lastRenderedIndex + this.pageSize)) {
437
- return false;
438
- }
439
- if (options === undefined) {
440
- options = { cursor: reset ? undefined : timeline?.cursor, limit: this.pageSize };
441
- }
442
- let request = this.pendingRequests.get(source);
443
- if (request !== undefined) {
444
- options.cursor = request.options.cursor;
445
- if (typeof options.limit === 'number') {
446
- if (typeof request.options.limit === 'number') {
447
- options.limit += request.options.limit;
448
- }
449
- else {
450
- options.limit = request.options.limit;
451
- }
452
- }
453
- }
454
- request?.tokenSource.dispose(true);
455
- options.cacheResults = true;
456
- options.resetCache = reset;
457
- request = this.timelineService.getTimeline(source, uri, options, ( new CancellationTokenSource()));
458
- if (request === undefined) {
459
- return false;
460
- }
461
- this.pendingRequests.set(source, request);
462
- request.tokenSource.token.onCancellationRequested(() => this.pendingRequests.delete(source));
463
- this.handleRequest(request);
464
- return true;
465
- }
466
- updateTimeline(timeline, reset) {
467
- if (reset) {
468
- this.timelinesBySource.delete(timeline.source);
469
- const { oldest } = timeline;
470
- this.loadTimelineForSource(timeline.source, this.uri, true, oldest !== undefined ? { limit: { timestamp: oldest.timestamp, id: oldest.id } } : undefined);
471
- }
472
- else {
473
- const { newest } = timeline;
474
- this.loadTimelineForSource(timeline.source, this.uri, false, newest !== undefined ? { limit: { timestamp: newest.timestamp, id: newest.id } } : { limit: this.pageSize });
475
- }
476
- }
477
- async handleRequest(request) {
478
- let response;
479
- try {
480
- response = await this.progressService.withProgress({ location: this.id }, () => request.result);
481
- }
482
- finally {
483
- this.pendingRequests.delete(request.source);
484
- }
485
- if (response === undefined ||
486
- request.tokenSource.token.isCancellationRequested ||
487
- request.uri !== this.uri) {
488
- if (this.pendingRequests.size === 0 && this._pendingRefresh) {
489
- this.refresh();
490
- }
491
- return;
492
- }
493
- const source = request.source;
494
- let updated = false;
495
- const timeline = this.timelinesBySource.get(source);
496
- if (timeline === undefined) {
497
- this.timelinesBySource.set(source, ( new TimelineAggregate(response)));
498
- updated = true;
499
- }
500
- else {
501
- updated = timeline.add(response, request.options);
502
- }
503
- if (updated) {
504
- this._pendingRefresh = true;
505
- if (this.hasVisibleItems && this.pendingRequests.size !== 0) {
506
- this.refreshDebounced();
507
- }
508
- else {
509
- this.refresh();
510
- }
511
- }
512
- else if (this.pendingRequests.size === 0) {
513
- if (this._pendingRefresh) {
514
- this.refresh();
515
- }
516
- else {
517
- this.tree.rerender();
518
- }
519
- }
520
- }
521
- *getItems() {
522
- let more = false;
523
- if (this.uri === undefined || this.timelinesBySource.size === 0) {
524
- this._visibleItemCount = 0;
525
- return;
526
- }
527
- const maxCount = this._maxItemCount;
528
- let count = 0;
529
- if (this.timelinesBySource.size === 1) {
530
- const [source, timeline] = Iterable.first(this.timelinesBySource);
531
- timeline.lastRenderedIndex = -1;
532
- if (( this.excludedSources.has(source))) {
533
- this._visibleItemCount = 0;
534
- return;
535
- }
536
- if (timeline.items.length !== 0) {
537
- this._visibleItemCount = 1;
538
- }
539
- more = timeline.more;
540
- let lastRelativeTime;
541
- for (const item of timeline.items) {
542
- item.relativeTime = undefined;
543
- item.hideRelativeTime = undefined;
544
- count++;
545
- if (count > maxCount) {
546
- more = true;
547
- break;
548
- }
549
- lastRelativeTime = updateRelativeTime(item, lastRelativeTime);
550
- yield { element: item };
551
- }
552
- timeline.lastRenderedIndex = count - 1;
553
- }
554
- else {
555
- const sources = [];
556
- let hasAnyItems = false;
557
- let mostRecentEnd = 0;
558
- for (const [source, timeline] of this.timelinesBySource) {
559
- timeline.lastRenderedIndex = -1;
560
- if (( this.excludedSources.has(source)) || timeline.stale) {
561
- continue;
562
- }
563
- if (timeline.items.length !== 0) {
564
- hasAnyItems = true;
565
- }
566
- if (timeline.more) {
567
- more = true;
568
- const last = timeline.items[Math.min(maxCount, timeline.items.length - 1)];
569
- if (last.timestamp > mostRecentEnd) {
570
- mostRecentEnd = last.timestamp;
571
- }
572
- }
573
- const iterator = timeline.items[Symbol.iterator]();
574
- sources.push({ timeline, iterator, nextItem: iterator.next() });
575
- }
576
- this._visibleItemCount = hasAnyItems ? 1 : 0;
577
- function getNextMostRecentSource() {
578
- return sources
579
- .filter(source => !source.nextItem.done)
580
- .reduce((previous, current) => (previous === undefined || current.nextItem.value.timestamp >= previous.nextItem.value.timestamp) ? current : previous, undefined);
581
- }
582
- let lastRelativeTime;
583
- let nextSource;
584
- while (nextSource = getNextMostRecentSource()) {
585
- nextSource.timeline.lastRenderedIndex++;
586
- const item = nextSource.nextItem.value;
587
- item.relativeTime = undefined;
588
- item.hideRelativeTime = undefined;
589
- if (item.timestamp >= mostRecentEnd) {
590
- count++;
591
- if (count > maxCount) {
592
- more = true;
593
- break;
594
- }
595
- lastRelativeTime = updateRelativeTime(item, lastRelativeTime);
596
- yield { element: item };
597
- }
598
- nextSource.nextItem = nextSource.iterator.next();
599
- }
600
- }
601
- this._visibleItemCount = count;
602
- if (count > 0) {
603
- if (more) {
604
- yield {
605
- element: ( new LoadMoreCommand(this.pendingRequests.size !== 0))
606
- };
607
- }
608
- else if (this.pendingRequests.size !== 0) {
609
- yield {
610
- element: ( new LoadMoreCommand(true))
611
- };
612
- }
613
- }
614
- }
615
- refresh() {
616
- if (!this.isBodyVisible()) {
617
- return;
618
- }
619
- this.tree.setChildren(null, this.getItems());
620
- this._isEmpty = !this.hasVisibleItems;
621
- if (this.uri === undefined) {
622
- this.updateFilename(undefined);
623
- this.message = ( localizeWithPath(
624
- 'vs/workbench/contrib/timeline/browser/timelinePane',
625
- 'timeline.editorCannotProvideTimeline',
626
- "The active editor cannot provide timeline information."
627
- ));
628
- }
629
- else if (this._isEmpty) {
630
- if (this.pendingRequests.size !== 0) {
631
- this.setLoadingUriMessage();
632
- }
633
- else {
634
- this.updateFilename(this.labelService.getUriBasenameLabel(this.uri));
635
- const scmProviderCount = this.contextKeyService.getContextKeyValue('scm.providerCount');
636
- if (this.timelineService.getSources().filter(({ id }) => !( this.excludedSources.has(id))).length === 0) {
637
- this.message = ( localizeWithPath(
638
- 'vs/workbench/contrib/timeline/browser/timelinePane',
639
- 'timeline.noTimelineSourcesEnabled',
640
- "All timeline sources have been filtered out."
641
- ));
642
- }
643
- else {
644
- if (this.configurationService.getValue('workbench.localHistory.enabled') && !( this.excludedSources.has('timeline.localHistory'))) {
645
- this.message = ( localizeWithPath(
646
- 'vs/workbench/contrib/timeline/browser/timelinePane',
647
- 'timeline.noLocalHistoryYet',
648
- "Local History will track recent changes as you save them unless the file has been excluded or is too large."
649
- ));
650
- }
651
- else if (this.excludedSources.size > 0) {
652
- this.message = ( localizeWithPath(
653
- 'vs/workbench/contrib/timeline/browser/timelinePane',
654
- 'timeline.noTimelineInfoFromEnabledSources',
655
- "No filtered timeline information was provided."
656
- ));
657
- }
658
- else {
659
- this.message = ( localizeWithPath(
660
- 'vs/workbench/contrib/timeline/browser/timelinePane',
661
- 'timeline.noTimelineInfo',
662
- "No timeline information was provided."
663
- ));
664
- }
665
- }
666
- if (!scmProviderCount || scmProviderCount === 0) {
667
- this.message += ' ' + ( localizeWithPath(
668
- 'vs/workbench/contrib/timeline/browser/timelinePane',
669
- 'timeline.noSCM',
670
- "Source Control has not been configured."
671
- ));
672
- }
673
- }
674
- }
675
- else {
676
- this.updateFilename(this.labelService.getUriBasenameLabel(this.uri));
677
- this.message = undefined;
678
- }
679
- this._pendingRefresh = false;
680
- }
681
- refreshDebounced() {
682
- this.refresh();
683
- }
684
- focus() {
685
- super.focus();
686
- this.tree.domFocus();
687
- }
688
- setExpanded(expanded) {
689
- const changed = super.setExpanded(expanded);
690
- if (changed && this.isBodyVisible()) {
691
- if (!this.followActiveEditor) {
692
- this.setUriCore(this.uri, true);
693
- }
694
- else {
695
- this.onActiveEditorChanged();
696
- }
697
- }
698
- return changed;
699
- }
700
- setVisible(visible) {
701
- if (visible) {
702
- this.extensionService.activateByEvent('onView:timeline');
703
- this.visibilityDisposables = ( new DisposableStore());
704
- this.editorService.onDidActiveEditorChange(this.onActiveEditorChanged, this, this.visibilityDisposables);
705
- this.onDidFocus(() => this.refreshDebounced(), this, this.visibilityDisposables);
706
- super.setVisible(visible);
707
- this.onActiveEditorChanged();
708
- }
709
- else {
710
- this.visibilityDisposables?.dispose();
711
- super.setVisible(visible);
712
- }
713
- }
714
- layoutBody(height, width) {
715
- super.layoutBody(height, width);
716
- this.tree.layout(height, width);
717
- }
718
- renderHeaderTitle(container) {
719
- super.renderHeaderTitle(container, this.title);
720
- container.classList.add('timeline-view');
721
- }
722
- renderBody(container) {
723
- super.renderBody(container);
724
- this.$container = container;
725
- container.classList.add('tree-explorer-viewlet-tree-view', 'timeline-tree-view');
726
- this.$message = append(this.$container, $('.message'));
727
- this.$message.classList.add('timeline-subtle');
728
- this.message = ( localizeWithPath(
729
- 'vs/workbench/contrib/timeline/browser/timelinePane',
730
- 'timeline.editorCannotProvideTimeline',
731
- "The active editor cannot provide timeline information."
732
- ));
733
- this.$tree = document.createElement('div');
734
- this.$tree.classList.add('customview-tree', 'file-icon-themable-tree', 'hide-arrows');
735
- container.appendChild(this.$tree);
736
- this.treeRenderer = this.instantiationService.createInstance(TimelineTreeRenderer, this.commands);
737
- this.treeRenderer.onDidScrollToEnd(item => {
738
- if (this.pageOnScroll) {
739
- this.loadMore(item);
740
- }
741
- });
742
- this.tree = this.instantiationService.createInstance(WorkbenchObjectTree, 'TimelinePane', this.$tree, ( new TimelineListVirtualDelegate()), [this.treeRenderer], {
743
- identityProvider: ( new TimelineIdentityProvider()),
744
- accessibilityProvider: {
745
- getAriaLabel(element) {
746
- if (isLoadMoreCommand(element)) {
747
- return element.ariaLabel;
748
- }
749
- return element.accessibilityInformation ? element.accessibilityInformation.label : ( localizeWithPath(
750
- 'vs/workbench/contrib/timeline/browser/timelinePane',
751
- 'timeline.aria.item',
752
- "{0}: {1}",
753
- element.relativeTimeFullWord ?? '',
754
- element.label
755
- ));
756
- },
757
- getRole(element) {
758
- if (isLoadMoreCommand(element)) {
759
- return 'treeitem';
760
- }
761
- return element.accessibilityInformation && element.accessibilityInformation.role ? element.accessibilityInformation.role : 'treeitem';
762
- },
763
- getWidgetAriaLabel() {
764
- return ( localizeWithPath(
765
- 'vs/workbench/contrib/timeline/browser/timelinePane',
766
- 'timeline',
767
- "Timeline"
768
- ));
769
- }
770
- },
771
- keyboardNavigationLabelProvider: ( new TimelineKeyboardNavigationLabelProvider()),
772
- multipleSelectionSupport: false,
773
- overrideStyles: {
774
- listBackground: this.getBackgroundColor()
775
- }
776
- });
777
- this._register(this.tree.onContextMenu(e => this.onContextMenu(this.commands, e)));
778
- this._register(this.tree.onDidChangeSelection(e => this.ensureValidItems()));
779
- this._register(this.tree.onDidOpen(e => {
780
- if (!e.browserEvent || !this.ensureValidItems()) {
781
- return;
782
- }
783
- const selection = this.tree.getSelection();
784
- let item;
785
- if (selection.length === 1) {
786
- item = selection[0];
787
- }
788
- if (item === null) {
789
- return;
790
- }
791
- if (isTimelineItem(item)) {
792
- if (item.command) {
793
- let args = item.command.arguments ?? [];
794
- if (item.command.id === API_OPEN_EDITOR_COMMAND_ID || item.command.id === API_OPEN_DIFF_EDITOR_COMMAND_ID) {
795
- args = [...args, e];
796
- }
797
- this.commandService.executeCommand(item.command.id, ...args);
798
- }
799
- }
800
- else if (isLoadMoreCommand(item)) {
801
- this.loadMore(item);
802
- }
803
- }));
804
- }
805
- loadMore(item) {
806
- if (item.loading) {
807
- return;
808
- }
809
- item.loading = true;
810
- this.tree.rerender(item);
811
- if (this.pendingRequests.size !== 0) {
812
- return;
813
- }
814
- this._maxItemCount = this._visibleItemCount + this.pageSize;
815
- this.loadTimeline(false);
816
- }
817
- ensureValidItems() {
818
- if (!this.hasVisibleItems || !( this.timelineService.getSources().some(({ id }) => !( this.excludedSources.has(id)) && ( this.timelinesBySource.has(id))))) {
819
- this.tree.setChildren(null, undefined);
820
- this._isEmpty = true;
821
- this.setLoadingUriMessage();
822
- return false;
823
- }
824
- return true;
825
- }
826
- setLoadingUriMessage() {
827
- const file = this.uri && this.labelService.getUriBasenameLabel(this.uri);
828
- this.updateFilename(file);
829
- this.message = file ? ( localizeWithPath(
830
- 'vs/workbench/contrib/timeline/browser/timelinePane',
831
- 'timeline.loading',
832
- "Loading timeline for {0}...",
833
- file
834
- )) : '';
835
- }
836
- onContextMenu(commands, treeEvent) {
837
- const item = treeEvent.element;
838
- if (item === null) {
839
- return;
840
- }
841
- const event = treeEvent.browserEvent;
842
- event.preventDefault();
843
- event.stopPropagation();
844
- if (!this.ensureValidItems()) {
845
- return;
846
- }
847
- this.tree.setFocus([item]);
848
- const actions = commands.getItemContextActions(item);
849
- if (!actions.length) {
850
- return;
851
- }
852
- this.contextMenuService.showContextMenu({
853
- getAnchor: () => treeEvent.anchor,
854
- getActions: () => actions,
855
- getActionViewItem: (action) => {
856
- const keybinding = this.keybindingService.lookupKeybinding(action.id);
857
- if (keybinding) {
858
- return ( new ActionViewItem(action, action, { label: true, keybinding: keybinding.getLabel() }));
859
- }
860
- return undefined;
861
- },
862
- onHide: (wasCancelled) => {
863
- if (wasCancelled) {
864
- this.tree.domFocus();
865
- }
866
- },
867
- getActionsContext: () => ({ uri: this.uri, item }),
868
- actionRunner: ( new TimelineActionRunner())
869
- });
870
- }
871
- };
872
- TimelinePane.__decorator = ( __decorate([
873
- debounce(500)
874
- ], TimelinePane.prototype, "refreshDebounced", null));
875
- TimelinePane = ( __decorate([
876
- ( __param(1, IKeybindingService)),
877
- ( __param(2, IContextMenuService)),
878
- ( __param(3, IContextKeyService)),
879
- ( __param(4, IConfigurationService)),
880
- ( __param(5, IStorageService)),
881
- ( __param(6, IViewDescriptorService)),
882
- ( __param(7, IInstantiationService)),
883
- ( __param(8, IEditorService)),
884
- ( __param(9, ICommandService)),
885
- ( __param(10, IProgressService)),
886
- ( __param(11, ITimelineService)),
887
- ( __param(12, IOpenerService)),
888
- ( __param(13, IThemeService)),
889
- ( __param(14, ITelemetryService)),
890
- ( __param(15, ILabelService)),
891
- ( __param(16, IUriIdentityService)),
892
- ( __param(17, IExtensionService))
893
- ], TimelinePane));
894
- class TimelineElementTemplate {
895
- static { this.id = 'TimelineElementTemplate'; }
896
- constructor(container, actionViewItemProvider, hoverDelegate) {
897
- container.classList.add('custom-view-tree-node-item');
898
- this.icon = append(container, $('.custom-view-tree-node-item-icon'));
899
- this.iconLabel = ( new IconLabel(container, { supportHighlights: true, supportIcons: true, hoverDelegate }));
900
- const timestampContainer = append(this.iconLabel.element, $('.timeline-timestamp-container'));
901
- this.timestamp = append(timestampContainer, $('span.timeline-timestamp'));
902
- const actionsContainer = append(this.iconLabel.element, $('.actions'));
903
- this.actionBar = ( new ActionBar(actionsContainer, { actionViewItemProvider }));
904
- }
905
- dispose() {
906
- this.iconLabel.dispose();
907
- this.actionBar.dispose();
908
- }
909
- reset() {
910
- this.icon.className = '';
911
- this.icon.style.backgroundImage = '';
912
- this.actionBar.clear();
913
- }
914
- }
915
- class TimelineIdentityProvider {
916
- getId(item) {
917
- return item.handle;
918
- }
919
- }
920
- class TimelineActionRunner extends ActionRunner {
921
- async runAction(action, { uri, item }) {
922
- if (!isTimelineItem(item)) {
923
- await action.run();
924
- return;
925
- }
926
- await action.run({
927
- $mid: 12 ,
928
- handle: item.handle,
929
- source: item.source,
930
- uri
931
- }, uri, item.source);
932
- }
933
- }
934
- class TimelineKeyboardNavigationLabelProvider {
935
- getKeyboardNavigationLabel(element) {
936
- return element.label;
937
- }
938
- }
939
- class TimelineListVirtualDelegate {
940
- getHeight(_element) {
941
- return ItemHeight;
942
- }
943
- getTemplateId(element) {
944
- return TimelineElementTemplate.id;
945
- }
946
- }
947
- let TimelineTreeRenderer = class TimelineTreeRenderer {
948
- constructor(commands, instantiationService, themeService) {
949
- this.commands = commands;
950
- this.instantiationService = instantiationService;
951
- this.themeService = themeService;
952
- this._onDidScrollToEnd = ( new Emitter());
953
- this.onDidScrollToEnd = this._onDidScrollToEnd.event;
954
- this.templateId = TimelineElementTemplate.id;
955
- this.actionViewItemProvider = createActionViewItem.bind(undefined, this.instantiationService);
956
- this._hoverDelegate = getDefaultHoverDelegate('mouse');
957
- }
958
- setUri(uri) {
959
- this.uri = uri;
960
- }
961
- renderTemplate(container) {
962
- return ( new TimelineElementTemplate(container, this.actionViewItemProvider, this._hoverDelegate));
963
- }
964
- renderElement(node, index, template, height) {
965
- template.reset();
966
- const { element: item } = node;
967
- const theme = this.themeService.getColorTheme();
968
- const icon = theme.type === ColorScheme.LIGHT ? item.icon : item.iconDark;
969
- const iconUrl = icon ? URI.revive(icon) : null;
970
- if (iconUrl) {
971
- template.icon.className = 'custom-view-tree-node-item-icon';
972
- template.icon.style.backgroundImage = asCSSUrl(iconUrl);
973
- template.icon.style.color = '';
974
- }
975
- else if (item.themeIcon) {
976
- template.icon.className = `custom-view-tree-node-item-icon ${ThemeIcon.asClassName(item.themeIcon)}`;
977
- if (item.themeIcon.color) {
978
- template.icon.style.color = theme.getColor(item.themeIcon.color.id)?.toString() ?? '';
979
- }
980
- else {
981
- template.icon.style.color = '';
982
- }
983
- template.icon.style.backgroundImage = '';
984
- }
985
- else {
986
- template.icon.className = 'custom-view-tree-node-item-icon';
987
- template.icon.style.backgroundImage = '';
988
- template.icon.style.color = '';
989
- }
990
- const tooltip = item.tooltip
991
- ? isString(item.tooltip)
992
- ? item.tooltip
993
- : { markdown: item.tooltip, markdownNotSupportedFallback: renderMarkdownAsPlaintext(item.tooltip) }
994
- : undefined;
995
- template.iconLabel.setLabel(item.label, item.description, {
996
- title: tooltip,
997
- matches: createMatches(node.filterData)
998
- });
999
- template.timestamp.textContent = item.relativeTime ?? '';
1000
- template.timestamp.ariaLabel = item.relativeTimeFullWord ?? '';
1001
- template.timestamp.parentElement.classList.toggle('timeline-timestamp--duplicate', isTimelineItem(item) && item.hideRelativeTime);
1002
- template.actionBar.context = { uri: this.uri, item };
1003
- template.actionBar.actionRunner = ( new TimelineActionRunner());
1004
- template.actionBar.push(this.commands.getItemActions(item), { icon: true, label: false });
1005
- if (isLoadMoreCommand(item)) {
1006
- setTimeout(() => this._onDidScrollToEnd.fire(item), 0);
1007
- }
1008
- }
1009
- disposeTemplate(template) {
1010
- template.dispose();
1011
- }
1012
- };
1013
- TimelineTreeRenderer = ( __decorate([
1014
- ( __param(1, IInstantiationService)),
1015
- ( __param(2, IThemeService))
1016
- ], TimelineTreeRenderer));
1017
- const timelineRefresh = registerIcon('timeline-refresh', Codicon.refresh, ( localizeWithPath(
1018
- 'vs/workbench/contrib/timeline/browser/timelinePane',
1019
- 'timelineRefresh',
1020
- 'Icon for the refresh timeline action.'
1021
- )));
1022
- const timelinePin = registerIcon('timeline-pin', Codicon.pin, ( localizeWithPath(
1023
- 'vs/workbench/contrib/timeline/browser/timelinePane',
1024
- 'timelinePin',
1025
- 'Icon for the pin timeline action.'
1026
- )));
1027
- const timelineUnpin = registerIcon('timeline-unpin', Codicon.pinned, ( localizeWithPath(
1028
- 'vs/workbench/contrib/timeline/browser/timelinePane',
1029
- 'timelineUnpin',
1030
- 'Icon for the unpin timeline action.'
1031
- )));
1032
- let TimelinePaneCommands = class TimelinePaneCommands extends Disposable {
1033
- constructor(pane, timelineService, storageService, contextKeyService, menuService) {
1034
- super();
1035
- this.pane = pane;
1036
- this.timelineService = timelineService;
1037
- this.storageService = storageService;
1038
- this.contextKeyService = contextKeyService;
1039
- this.menuService = menuService;
1040
- this._register(this.sourceDisposables = ( new DisposableStore()));
1041
- this._register(registerAction2(class extends Action2 {
1042
- constructor() {
1043
- super({
1044
- id: 'timeline.refresh',
1045
- title: ( localize2WithPath('vs/workbench/contrib/timeline/browser/timelinePane', 'refresh', "Refresh")),
1046
- icon: timelineRefresh,
1047
- category: ( localize2WithPath(
1048
- 'vs/workbench/contrib/timeline/browser/timelinePane',
1049
- 'timeline',
1050
- "Timeline"
1051
- )),
1052
- menu: {
1053
- id: MenuId.TimelineTitle,
1054
- group: 'navigation',
1055
- order: 99,
1056
- }
1057
- });
1058
- }
1059
- run(accessor, ...args) {
1060
- pane.reset();
1061
- }
1062
- }));
1063
- this._register(CommandsRegistry.registerCommand('timeline.toggleFollowActiveEditor', (accessor, ...args) => pane.followActiveEditor = !pane.followActiveEditor));
1064
- this._register(MenuRegistry.appendMenuItem(MenuId.TimelineTitle, ({
1065
- command: {
1066
- id: 'timeline.toggleFollowActiveEditor',
1067
- title: ( localize2WithPath(
1068
- 'vs/workbench/contrib/timeline/browser/timelinePane',
1069
- 'timeline.toggleFollowActiveEditorCommand.follow',
1070
- 'Pin the Current Timeline'
1071
- )),
1072
- icon: timelinePin,
1073
- category: ( localize2WithPath(
1074
- 'vs/workbench/contrib/timeline/browser/timelinePane',
1075
- 'timeline',
1076
- "Timeline"
1077
- )),
1078
- },
1079
- group: 'navigation',
1080
- order: 98,
1081
- when: TimelineFollowActiveEditorContext
1082
- })));
1083
- this._register(MenuRegistry.appendMenuItem(MenuId.TimelineTitle, ({
1084
- command: {
1085
- id: 'timeline.toggleFollowActiveEditor',
1086
- title: ( localize2WithPath(
1087
- 'vs/workbench/contrib/timeline/browser/timelinePane',
1088
- 'timeline.toggleFollowActiveEditorCommand.unfollow',
1089
- 'Unpin the Current Timeline'
1090
- )),
1091
- icon: timelineUnpin,
1092
- category: ( localize2WithPath(
1093
- 'vs/workbench/contrib/timeline/browser/timelinePane',
1094
- 'timeline',
1095
- "Timeline"
1096
- )),
1097
- },
1098
- group: 'navigation',
1099
- order: 98,
1100
- when: ( TimelineFollowActiveEditorContext.toNegated())
1101
- })));
1102
- this._register(timelineService.onDidChangeProviders(() => this.updateTimelineSourceFilters()));
1103
- this.updateTimelineSourceFilters();
1104
- }
1105
- getItemActions(element) {
1106
- return this.getActions(MenuId.TimelineItemContext, { key: 'timelineItem', value: element.contextValue }).primary;
1107
- }
1108
- getItemContextActions(element) {
1109
- return this.getActions(MenuId.TimelineItemContext, { key: 'timelineItem', value: element.contextValue }).secondary;
1110
- }
1111
- getActions(menuId, context) {
1112
- const contextKeyService = this.contextKeyService.createOverlay([
1113
- ['view', this.pane.id],
1114
- [context.key, context.value],
1115
- ]);
1116
- const menu = this.menuService.createMenu(menuId, contextKeyService);
1117
- const primary = [];
1118
- const secondary = [];
1119
- const result = { primary, secondary };
1120
- createAndFillInContextMenuActions(menu, { shouldForwardArgs: true }, result, 'inline');
1121
- menu.dispose();
1122
- return result;
1123
- }
1124
- updateTimelineSourceFilters() {
1125
- this.sourceDisposables.clear();
1126
- const excluded = ( new Set(
1127
- JSON.parse(this.storageService.get('timeline.excludeSources', 0 , '[]'))
1128
- ));
1129
- for (const source of this.timelineService.getSources()) {
1130
- this.sourceDisposables.add(registerAction2(class extends Action2 {
1131
- constructor() {
1132
- super({
1133
- id: `timeline.toggleExcludeSource:${source.id}`,
1134
- title: source.label,
1135
- menu: {
1136
- id: MenuId.TimelineFilterSubMenu,
1137
- group: 'navigation',
1138
- },
1139
- toggled: ( ( ContextKeyExpr.regex(`timelineExcludeSources`, ( new RegExp(`\\b${escapeRegExpCharacters(source.id)}\\b`)))).negate())
1140
- });
1141
- }
1142
- run(accessor, ...args) {
1143
- if (( excluded.has(source.id))) {
1144
- excluded.delete(source.id);
1145
- }
1146
- else {
1147
- excluded.add(source.id);
1148
- }
1149
- const storageService = accessor.get(IStorageService);
1150
- storageService.store('timeline.excludeSources', JSON.stringify([...( excluded.keys())]), 0 , 0 );
1151
- }
1152
- }));
1153
- }
1154
- }
1155
- };
1156
- TimelinePaneCommands = ( __decorate([
1157
- ( __param(1, ITimelineService)),
1158
- ( __param(2, IStorageService)),
1159
- ( __param(3, IContextKeyService)),
1160
- ( __param(4, IMenuService))
1161
- ], TimelinePaneCommands));
1162
-
1163
- export { TimelineExcludeSources, TimelineFollowActiveEditorContext, TimelineIdentityProvider, TimelineKeyboardNavigationLabelProvider, TimelineListVirtualDelegate, TimelinePane };