Skip to content

Commit aef1a6c

Browse files
committed
add setting: scm.countBadge
fixes microsoft#78610
1 parent bd30caa commit aef1a6c

2 files changed

Lines changed: 63 additions & 73 deletions

File tree

src/vs/workbench/contrib/scm/browser/scm.contribution.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions } fro
1313
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
1414
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
1515
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
16-
import { StatusUpdater, StatusBarController } from './scmActivity';
16+
import { SCMStatusController } from './scmActivity';
1717
import { SCMViewlet } from 'vs/workbench/contrib/scm/browser/scmViewlet';
1818
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
1919
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
@@ -47,10 +47,7 @@ Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(new Vie
4747
));
4848

4949
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
50-
.registerWorkbenchContribution(StatusUpdater, LifecyclePhase.Restored);
51-
52-
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
53-
.registerWorkbenchContribution(StatusBarController, LifecyclePhase.Restored);
50+
.registerWorkbenchContribution(SCMStatusController, LifecyclePhase.Restored);
5451

5552
// Register Action to Open Viewlet
5653
Registry.as<IWorkbenchActionRegistry>(WorkbenchActionExtensions.WorkbenchActions).registerWorkbenchAction(
@@ -97,6 +94,17 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
9794
type: 'boolean',
9895
description: localize('alwaysShowActions', "Controls whether inline actions are always visible in the Source Control view."),
9996
default: false
97+
},
98+
'scm.countBadge': {
99+
type: 'string',
100+
enum: ['all', 'focused', 'off'],
101+
enumDescriptions: [
102+
localize('scm.countBadge.all', "Show the sum of all Source Control Providers count badges."),
103+
localize('scm.countBadge.focused', "Show the count badge of the focused Source Control Provider."),
104+
localize('scm.countBadge.off', "Disable the Source Control count badge.")
105+
],
106+
description: localize('scm.countBadge', "Controls the Source Control count badge."),
107+
default: 'all'
100108
}
101109
}
102110
});

src/vs/workbench/contrib/scm/browser/scmActivity.ts

Lines changed: 50 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -14,92 +14,45 @@ import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/c
1414
import { IStatusbarService, StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/platform/statusbar/common/statusbar';
1515
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
1616
import { commonPrefixLength } from 'vs/base/common/strings';
17-
import { ILogService } from 'vs/platform/log/common/log';
17+
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
1818

19-
export class StatusUpdater implements IWorkbenchContribution {
20-
21-
private readonly badgeDisposable = new MutableDisposable<IDisposable>();
22-
private disposables: IDisposable[] = [];
23-
24-
constructor(
25-
@ISCMService private readonly scmService: ISCMService,
26-
@IActivityService private readonly activityService: IActivityService,
27-
@ILogService private readonly logService: ILogService
28-
) {
29-
for (const repository of this.scmService.repositories) {
30-
this.onDidAddRepository(repository);
31-
}
32-
33-
this.scmService.onDidAddRepository(this.onDidAddRepository, this, this.disposables);
34-
this.render();
35-
}
36-
37-
private onDidAddRepository(repository: ISCMRepository): void {
38-
const provider = repository.provider;
39-
const onDidChange = Event.any(provider.onDidChange, provider.onDidChangeResources);
40-
const changeDisposable = onDidChange(() => this.render());
41-
42-
const onDidRemove = Event.filter(this.scmService.onDidRemoveRepository, e => e === repository);
43-
const removeDisposable = onDidRemove(() => {
44-
disposable.dispose();
45-
this.disposables = this.disposables.filter(d => d !== removeDisposable);
46-
this.render();
47-
});
48-
49-
const disposable = combinedDisposable(changeDisposable, removeDisposable);
50-
this.disposables.push(disposable);
51-
}
52-
53-
private render(): void {
54-
this.badgeDisposable.clear();
55-
56-
const count = this.scmService.repositories.reduce((r, repository) => {
57-
if (typeof repository.provider.count === 'number') {
58-
return r + repository.provider.count;
59-
} else {
60-
return r + repository.provider.groups.elements.reduce<number>((r, g) => r + g.elements.length, 0);
61-
}
62-
}, 0);
63-
64-
// TODO@joao: remove
65-
this.logService.trace('SCM#StatusUpdater.render', count);
66-
67-
if (count > 0) {
68-
const badge = new NumberBadge(count, num => localize('scmPendingChangesBadge', '{0} pending changes', num));
69-
this.badgeDisposable.value = this.activityService.showActivity(VIEWLET_ID, badge, 'scm-viewlet-label');
70-
} else {
71-
this.badgeDisposable.clear();
72-
}
73-
}
74-
75-
dispose(): void {
76-
this.badgeDisposable.dispose();
77-
this.disposables = dispose(this.disposables);
19+
function getCount(repository: ISCMRepository): number {
20+
if (typeof repository.provider.count === 'number') {
21+
return repository.provider.count;
22+
} else {
23+
return repository.provider.groups.elements.reduce<number>((r, g) => r + g.elements.length, 0);
7824
}
7925
}
8026

81-
export class StatusBarController implements IWorkbenchContribution {
27+
export class SCMStatusController implements IWorkbenchContribution {
8228

8329
private statusBarDisposable: IDisposable = Disposable.None;
8430
private focusDisposable: IDisposable = Disposable.None;
8531
private focusedRepository: ISCMRepository | undefined = undefined;
8632
private focusedProviderContextKey: IContextKey<string | undefined>;
33+
private readonly badgeDisposable = new MutableDisposable<IDisposable>();
8734
private disposables: IDisposable[] = [];
8835

8936
constructor(
9037
@ISCMService private readonly scmService: ISCMService,
9138
@IStatusbarService private readonly statusbarService: IStatusbarService,
92-
@IContextKeyService contextKeyService: IContextKeyService,
93-
@IEditorService private readonly editorService: IEditorService
39+
@IContextKeyService readonly contextKeyService: IContextKeyService,
40+
@IActivityService private readonly activityService: IActivityService,
41+
@IEditorService private readonly editorService: IEditorService,
42+
@IConfigurationService private readonly configurationService: IConfigurationService
9443
) {
9544
this.focusedProviderContextKey = contextKeyService.createKey<string | undefined>('scmProvider', undefined);
9645
this.scmService.onDidAddRepository(this.onDidAddRepository, this, this.disposables);
9746

47+
const onDidChangeSCMCountBadge = Event.filter(configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.countBadge'));
48+
onDidChangeSCMCountBadge(this.renderActivityCount, this, this.disposables);
49+
9850
for (const repository of this.scmService.repositories) {
9951
this.onDidAddRepository(repository);
10052
}
10153

10254
editorService.onDidActiveEditorChange(this.onDidActiveEditorChange, this, this.disposables);
55+
this.renderActivityCount();
10356
}
10457

10558
private onDidActiveEditorChange(): void {
@@ -138,7 +91,11 @@ export class StatusBarController implements IWorkbenchContribution {
13891
}
13992

14093
private onDidAddRepository(repository: ISCMRepository): void {
141-
const changeDisposable = repository.onDidFocus(() => this.onDidFocusRepository(repository));
94+
const focusDisposable = repository.onDidFocus(() => this.onDidFocusRepository(repository));
95+
96+
const onDidChange = Event.any(repository.provider.onDidChange, repository.provider.onDidChangeResources);
97+
const changeDisposable = onDidChange(() => this.renderActivityCount());
98+
14299
const onDidRemove = Event.filter(this.scmService.onDidRemoveRepository, e => e === repository);
143100
const removeDisposable = onDidRemove(() => {
144101
disposable.dispose();
@@ -149,9 +106,11 @@ export class StatusBarController implements IWorkbenchContribution {
149106
} else if (this.focusedRepository === repository) {
150107
this.scmService.repositories[0].focus();
151108
}
109+
110+
this.renderActivityCount();
152111
});
153112

154-
const disposable = combinedDisposable(changeDisposable, removeDisposable);
113+
const disposable = combinedDisposable(focusDisposable, changeDisposable, removeDisposable);
155114
this.disposables.push(disposable);
156115

157116
if (!this.focusedRepository) {
@@ -169,13 +128,14 @@ export class StatusBarController implements IWorkbenchContribution {
169128
this.focusDisposable.dispose();
170129

171130
if (repository && repository.provider.onDidChangeStatusBarCommands) {
172-
this.focusDisposable = repository.provider.onDidChangeStatusBarCommands(() => this.render(repository));
131+
this.focusDisposable = repository.provider.onDidChangeStatusBarCommands(() => this.renderStatusBar(repository));
173132
}
174133

175-
this.render(repository);
134+
this.renderStatusBar(repository);
135+
this.renderActivityCount();
176136
}
177137

178-
private render(repository: ISCMRepository | undefined): void {
138+
private renderStatusBar(repository: ISCMRepository | undefined): void {
179139
this.statusBarDisposable.dispose();
180140

181141
if (!repository) {
@@ -200,9 +160,31 @@ export class StatusBarController implements IWorkbenchContribution {
200160
this.statusBarDisposable = disposables;
201161
}
202162

163+
private renderActivityCount(): void {
164+
this.badgeDisposable.clear();
165+
166+
const countBadgeType = this.configurationService.getValue<'all' | 'focused' | 'off'>('scm.countBadge');
167+
168+
let count = 0;
169+
170+
if (countBadgeType === 'all') {
171+
count = this.scmService.repositories.reduce((r, repository) => r + getCount(repository), 0);
172+
} else if (countBadgeType === 'focused' && this.focusedRepository) {
173+
count = getCount(this.focusedRepository);
174+
}
175+
176+
if (count > 0) {
177+
const badge = new NumberBadge(count, num => localize('scmPendingChangesBadge', '{0} pending changes', num));
178+
this.badgeDisposable.value = this.activityService.showActivity(VIEWLET_ID, badge, 'scm-viewlet-label');
179+
} else {
180+
this.badgeDisposable.clear();
181+
}
182+
}
183+
203184
dispose(): void {
204185
this.focusDisposable.dispose();
205186
this.statusBarDisposable.dispose();
187+
this.badgeDisposable.dispose();
206188
this.disposables = dispose(this.disposables);
207189
}
208190
}

0 commit comments

Comments
 (0)