Skip to content

Commit 41f0ff1

Browse files
committed
deco - move scm decorations to git extension
1 parent 015901f commit 41f0ff1

13 files changed

Lines changed: 128 additions & 189 deletions

File tree

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
'use strict';
7+
8+
import { window, Uri, Disposable, Event, EventEmitter, DecorationData, DecorationProvider } from 'vscode';
9+
import { Repository, GitResourceGroup } from './repository';
10+
import { Model } from './model';
11+
12+
class GitDecorationProvider implements DecorationProvider {
13+
14+
private readonly _onDidChangeDecorations = new EventEmitter<Uri[]>();
15+
readonly onDidChangeDecorations: Event<Uri[]> = this._onDidChangeDecorations.event;
16+
17+
private disposables: Disposable[] = [];
18+
private decorations = new Map<string, DecorationData>();
19+
20+
constructor(private repository: Repository) {
21+
this.disposables.push(
22+
window.registerDecorationProvider(this, repository.root),
23+
repository.onDidRunOperation(this.onDidRunOperation, this)
24+
);
25+
}
26+
27+
private onDidRunOperation(): void {
28+
let newDecorations = new Map<string, DecorationData>();
29+
this.collectDecorationData(this.repository.indexGroup, newDecorations);
30+
this.collectDecorationData(this.repository.workingTreeGroup, newDecorations);
31+
32+
let uris: Uri[] = [];
33+
newDecorations.forEach((value, uriString) => {
34+
if (this.decorations.has(uriString)) {
35+
this.decorations.delete(uriString);
36+
} else {
37+
uris.push(Uri.parse(uriString));
38+
}
39+
});
40+
this.decorations.forEach((value, uriString) => {
41+
uris.push(Uri.parse(uriString));
42+
});
43+
this.decorations = newDecorations;
44+
this._onDidChangeDecorations.fire(uris);
45+
}
46+
47+
private collectDecorationData(group: GitResourceGroup, bucket: Map<string, DecorationData>): void {
48+
group.resourceStates.forEach(r => {
49+
if (r.resourceDecoration) {
50+
bucket.set(r.original.toString(), r.resourceDecoration);
51+
}
52+
});
53+
}
54+
55+
provideDecoration(uri: Uri): DecorationData | undefined {
56+
return this.decorations.get(uri.toString());
57+
}
58+
59+
dispose(): void {
60+
this.disposables.forEach(d => d.dispose());
61+
}
62+
}
63+
64+
65+
export class GitDecorations {
66+
67+
private disposables: Disposable[] = [];
68+
private providers = new Map<Repository, GitDecorationProvider>();
69+
70+
constructor(private model: Model) {
71+
this.disposables.push(
72+
model.onDidOpenRepository(this.onDidOpenRepository, this),
73+
model.onDidCloseRepository(this.onDidCloseRepository, this)
74+
);
75+
model.repositories.forEach(this.onDidOpenRepository, this);
76+
}
77+
78+
private onDidOpenRepository(repository: Repository): void {
79+
const provider = new GitDecorationProvider(repository);
80+
this.providers.set(repository, provider);
81+
}
82+
83+
private onDidCloseRepository(repository: Repository): void {
84+
const provider = this.providers.get(repository);
85+
if (provider) {
86+
provider.dispose();
87+
this.providers.delete(repository);
88+
}
89+
}
90+
91+
dispose(): void {
92+
this.disposables.forEach(d => d.dispose());
93+
this.providers.forEach(value => value.dispose);
94+
this.providers.clear();
95+
}
96+
}

extensions/git/src/main.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { findGit, Git, IGit } from './git';
1212
import { Model } from './model';
1313
import { CommandCenter } from './commands';
1414
import { GitContentProvider } from './contentProvider';
15+
import { GitDecorations } from './decorationProvider';
1516
import { Askpass } from './askpass';
1617
import { toDisposable } from './util';
1718
import TelemetryReporter from 'vscode-extension-telemetry';
@@ -54,6 +55,7 @@ async function init(context: ExtensionContext, disposables: Disposable[]): Promi
5455
disposables.push(
5556
new CommandCenter(git, model, outputChannel, telemetryReporter),
5657
new GitContentProvider(model),
58+
new GitDecorations(model)
5759
);
5860

5961
await checkGitVersion(info);
@@ -93,4 +95,4 @@ async function checkGitVersion(info: IGit): Promise<void> {
9395
} else if (choice === neverShowAgain) {
9496
await config.update('ignoreLegacyWarning', true, true);
9597
}
96-
}
98+
}

extensions/git/src/repository.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
'use strict';
77

8-
import { Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor } from 'vscode';
8+
import { Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData } from 'vscode';
99
import { Repository as BaseRepository, Ref, Branch, Remote, Commit, GitErrorCodes, Stash, RefType } from './git';
1010
import { anyEvent, filterEvent, eventToPromise, dispose, find } from './util';
1111
import { memoize, throttle, debounce } from './decorators';
@@ -170,27 +170,29 @@ export class Resource implements SourceControlResourceState {
170170
// return this.resourceUri.fsPath.substr(0, workspaceRootPath.length) !== workspaceRootPath;
171171
}
172172

173-
private get color(): ThemeColor | undefined {
174-
switch (this.type) {
175-
case Status.INDEX_MODIFIED:
176-
case Status.MODIFIED:
177-
return new ThemeColor('git.color.modified');
178-
case Status.UNTRACKED:
179-
return new ThemeColor('git.color.untracked');
180-
default:
181-
return undefined;
182-
}
183-
}
184-
185173
get decorations(): SourceControlResourceDecorations {
186174
const light = { iconPath: this.getIconPath('light') };
187175
const dark = { iconPath: this.getIconPath('dark') };
188176
const tooltip = this.tooltip;
189177
const strikeThrough = this.strikeThrough;
190178
const faded = this.faded;
191-
const color = this.color;
192179

193-
return { strikeThrough, faded, tooltip, light, dark, color };
180+
return { strikeThrough, faded, tooltip, light, dark };
181+
}
182+
183+
get resourceDecoration(): DecorationData | undefined {
184+
const title = this.tooltip;
185+
switch (this.type) {
186+
case Status.IGNORED:
187+
return { priority: 3, title, opacity: 0.75 };
188+
case Status.UNTRACKED:
189+
return { priority: 1, title, abbreviation: localize('untracked, short', "U"), bubble: true, color: new ThemeColor('git.color.untracked') };
190+
case Status.INDEX_MODIFIED:
191+
case Status.MODIFIED:
192+
return { priority: 2, title, abbreviation: localize('modified, short', "M"), bubble: true, color: new ThemeColor('git.color.modified') };
193+
default:
194+
return undefined;
195+
}
194196
}
195197

196198
constructor(

src/vs/vscode.d.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5795,12 +5795,6 @@ declare module 'vscode' {
57955795
*/
57965796
readonly tooltip?: string;
57975797

5798-
/**
5799-
* A color for a specific
5800-
* [source control resource state](#SourceControlResourceState).
5801-
*/
5802-
readonly color?: ThemeColor;
5803-
58045798
/**
58055799
* The light theme decorations.
58065800
*/

src/vs/vscode.proposed.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ declare module 'vscode' {
175175
export interface DecorationData {
176176
priority?: number;
177177
title?: string;
178+
bubble?: boolean;
178179
abbreviation?: string;
179180
color?: ThemeColor;
180181
opacity?: number;

src/vs/workbench/api/electron-browser/mainThreadDecorations.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,13 @@ export class MainThreadDecorations implements MainThreadDecorationsShape {
3636
onDidChange: emitter.event,
3737
provideDecorations: (uri) => {
3838
return this._proxy.$providerDecorations(handle, uri).then(data => {
39-
const [weight, title, letter, opacity, themeColor] = data;
39+
if (!data) {
40+
return undefined;
41+
}
42+
const [weight, bubble, title, letter, opacity, themeColor] = data;
4043
return {
4144
weight: weight || 0,
45+
bubble: bubble || false,
4246
title,
4347
letter,
4448
opacity,

src/vs/workbench/api/electron-browser/mainThreadSCM.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,16 +182,15 @@ class MainThreadSCMProvider implements ISCMProvider {
182182

183183
for (const [start, deleteCount, rawResources] of groupSlices) {
184184
const resources = rawResources.map(rawResource => {
185-
const [handle, sourceUri, icons, tooltip, strikeThrough, faded, color] = rawResource;
185+
const [handle, sourceUri, icons, tooltip, strikeThrough, faded] = rawResource;
186186
const icon = icons[0];
187187
const iconDark = icons[1] || icon;
188188
const decorations = {
189189
icon: icon && URI.parse(icon),
190190
iconDark: iconDark && URI.parse(iconDark),
191191
tooltip,
192192
strikeThrough,
193-
faded,
194-
color: color && color.id
193+
faded
195194
};
196195

197196
return new MainThreadSCMResource(

src/vs/workbench/api/node/extHost.protocol.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,7 @@ export type SCMRawResource = [
362362
string[] /*icons: light, dark*/,
363363
string /*tooltip*/,
364364
boolean /*strike through*/,
365-
boolean /*faded*/,
366-
{ id: string } /*ThemeColor*/
365+
boolean /*faded*/
367366
];
368367

369368
export type SCMRawResourceSplice = [
@@ -603,7 +602,7 @@ export interface ExtHostDebugServiceShape {
603602
}
604603

605604

606-
export type DecorationData = [number, string, string, number, ThemeColor];
605+
export type DecorationData = [number, boolean, string, string, number, ThemeColor];
607606

608607
export interface ExtHostDecorationsShape {
609608
$providerDecorations(handle: number, uri: URI): TPromise<DecorationData>;

src/vs/workbench/api/node/extHostDecorations.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
4141
$providerDecorations(handle: number, uri: URI): TPromise<DecorationData> {
4242
const provider = this._provider.get(handle);
4343
return asWinJsPromise(token => provider.provideDecoration(uri, token)).then(data => {
44-
return <DecorationData>[data.priority, data.title, data.abbreviation, data.opacity, data.color];
44+
return data && <DecorationData>[data.priority, data.bubble, data.title, data.abbreviation, data.opacity, data.color];
4545
});
4646
}
4747
}

src/vs/workbench/api/node/extHostSCM.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,8 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
243243
const tooltip = (r.decorations && r.decorations.tooltip) || '';
244244
const strikeThrough = r.decorations && !!r.decorations.strikeThrough;
245245
const faded = r.decorations && !!r.decorations.faded;
246-
const color = r.decorations && r.decorations.color;
247246

248-
return [handle, sourceUri, icons, tooltip, strikeThrough, faded, color] as SCMRawResource;
247+
return [handle, sourceUri, icons, tooltip, strikeThrough, faded] as SCMRawResource;
249248
});
250249

251250
handlesToDelete.push(...this._handlesSnapshot.splice(start, deleteCount, ...handles));

0 commit comments

Comments
 (0)