@theia/scm 1.53.0-next.5 → 1.53.0-next.55

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 (41) hide show
  1. package/README.md +31 -31
  2. package/lib/browser/scm-commit-widget.js +1 -1
  3. package/lib/browser/scm-contribution.js +5 -5
  4. package/package.json +7 -7
  5. package/src/browser/decorations/scm-decorations-service.ts +102 -102
  6. package/src/browser/decorations/scm-navigator-decorator.ts +121 -121
  7. package/src/browser/decorations/scm-tab-bar-decorator.ts +83 -83
  8. package/src/browser/dirty-diff/content-lines.spec.ts +42 -42
  9. package/src/browser/dirty-diff/content-lines.ts +121 -121
  10. package/src/browser/dirty-diff/diff-computer.spec.ts +455 -455
  11. package/src/browser/dirty-diff/diff-computer.ts +177 -177
  12. package/src/browser/dirty-diff/dirty-diff-decorator.ts +114 -114
  13. package/src/browser/dirty-diff/dirty-diff-module.ts +33 -33
  14. package/src/browser/dirty-diff/dirty-diff-navigator.ts +288 -288
  15. package/src/browser/dirty-diff/dirty-diff-widget.ts +364 -364
  16. package/src/browser/scm-amend-component.tsx +600 -600
  17. package/src/browser/scm-amend-widget.tsx +77 -77
  18. package/src/browser/scm-avatar-service.ts +27 -27
  19. package/src/browser/scm-colors.ts +21 -21
  20. package/src/browser/scm-commit-widget.tsx +215 -215
  21. package/src/browser/scm-context-key-service.ts +46 -46
  22. package/src/browser/scm-contribution.ts +452 -452
  23. package/src/browser/scm-frontend-module.ts +149 -149
  24. package/src/browser/scm-groups-tree-model.ts +78 -78
  25. package/src/browser/scm-input.ts +164 -164
  26. package/src/browser/scm-layout-migrations.ts +64 -64
  27. package/src/browser/scm-no-repository-widget.tsx +41 -41
  28. package/src/browser/scm-preferences.ts +63 -63
  29. package/src/browser/scm-provider.ts +91 -91
  30. package/src/browser/scm-quick-open-service.ts +48 -48
  31. package/src/browser/scm-repository.ts +52 -52
  32. package/src/browser/scm-service.ts +108 -108
  33. package/src/browser/scm-tree-label-provider.ts +44 -44
  34. package/src/browser/scm-tree-model.ts +405 -405
  35. package/src/browser/scm-tree-widget.tsx +838 -838
  36. package/src/browser/scm-widget.tsx +204 -204
  37. package/src/browser/style/dirty-diff-decorator.css +53 -53
  38. package/src/browser/style/dirty-diff.css +50 -50
  39. package/src/browser/style/index.css +271 -271
  40. package/src/browser/style/scm-amend-component.css +94 -94
  41. package/src/browser/style/scm.svg +4 -4
package/README.md CHANGED
@@ -1,31 +1,31 @@
1
- <div align='center'>
2
-
3
- <br />
4
-
5
- <img src='https://raw.githubusercontent.com/eclipse-theia/theia/master/logo/theia.svg?sanitize=true' alt='theia-ext-logo' width='100px' />
6
-
7
- <h2>ECLIPSE THEIA - SCM EXTENSION</h2>
8
-
9
- <hr />
10
-
11
- </div>
12
-
13
- ## Description
14
-
15
- The `@theia/scm` extension adds support for handling multiple source control managers, and includes a `SCM` (Source Control Manager) View which different source control providers (such as `Git` and `Mercurial`) can contribute to.
16
-
17
- ## Additional Information
18
-
19
- - [API documentation for `@theia/scm`](https://eclipse-theia.github.io/theia/docs/next/modules/scm.html)
20
- - [Theia - GitHub](https://github.com/eclipse-theia/theia)
21
- - [Theia - Website](https://theia-ide.org/)
22
- - [VS Code SCM Documentation](https://code.visualstudio.com/docs/editor/versioncontrol)
23
-
24
- ## License
25
-
26
- - [Eclipse Public License 2.0](http://www.eclipse.org/legal/epl-2.0/)
27
- - [一 (Secondary) GNU General Public License, version 2 with the GNU Classpath Exception](https://projects.eclipse.org/license/secondary-gpl-2.0-cp)
28
-
29
- ## Trademark
30
- "Theia" is a trademark of the Eclipse Foundation
31
- https://www.eclipse.org/theia
1
+ <div align='center'>
2
+
3
+ <br />
4
+
5
+ <img src='https://raw.githubusercontent.com/eclipse-theia/theia/master/logo/theia.svg?sanitize=true' alt='theia-ext-logo' width='100px' />
6
+
7
+ <h2>ECLIPSE THEIA - SCM EXTENSION</h2>
8
+
9
+ <hr />
10
+
11
+ </div>
12
+
13
+ ## Description
14
+
15
+ The `@theia/scm` extension adds support for handling multiple source control managers, and includes a `SCM` (Source Control Manager) View which different source control providers (such as `Git` and `Mercurial`) can contribute to.
16
+
17
+ ## Additional Information
18
+
19
+ - [API documentation for `@theia/scm`](https://eclipse-theia.github.io/theia/docs/next/modules/scm.html)
20
+ - [Theia - GitHub](https://github.com/eclipse-theia/theia)
21
+ - [Theia - Website](https://theia-ide.org/)
22
+ - [VS Code SCM Documentation](https://code.visualstudio.com/docs/editor/versioncontrol)
23
+
24
+ ## License
25
+
26
+ - [Eclipse Public License 2.0](http://www.eclipse.org/legal/epl-2.0/)
27
+ - [一 (Secondary) GNU General Public License, version 2 with the GNU Classpath Exception](https://projects.eclipse.org/license/secondary-gpl-2.0-cp)
28
+
29
+ ## Trademark
30
+ "Theia" is a trademark of the Eclipse Foundation
31
+ https://www.eclipse.org/theia
@@ -121,7 +121,7 @@ let ScmCommitWidget = ScmCommitWidget_1 = class ScmCommitWidget extends browser_
121
121
  React.createElement(react_autosize_textarea_1.default, { className: `${ScmCommitWidget_1.Styles.INPUT_MESSAGE} theia-input theia-scm-input-message-${validationStatus}`, id: ScmCommitWidget_1.Styles.INPUT_MESSAGE, placeholder: message, spellCheck: false, autoFocus: true, value: input.value, disabled: !input.enabled, onChange: this.setInputValue, ref: this.inputRef, rows: 1, maxRows: 6 });
122
122
  return React.createElement("div", { className: ScmCommitWidget_1.Styles.INPUT_MESSAGE_CONTAINER },
123
123
  textArea,
124
- React.createElement("div", { className: `${ScmCommitWidget_1.Styles.VALIDATION_MESSAGE} ${ScmCommitWidget_1.Styles.NO_SELECT}
124
+ React.createElement("div", { className: `${ScmCommitWidget_1.Styles.VALIDATION_MESSAGE} ${ScmCommitWidget_1.Styles.NO_SELECT}
125
125
  theia-scm-validation-message-${validationStatus} theia-scm-input-message-${validationStatus}`, style: {
126
126
  display: !!input.issue ? 'block' : 'none'
127
127
  } }, validationMessage));
@@ -380,11 +380,11 @@ let ScmContribution = class ScmContribution extends browser_1.AbstractViewContri
380
380
  registerThemeStyle(theme, collector) {
381
381
  const contrastBorder = theme.getColor('contrastBorder');
382
382
  if (contrastBorder && (0, theme_1.isHighContrast)(theme.type)) {
383
- collector.addRule(`
384
- .theia-scm-input-message-container textarea {
385
- outline: var(--theia-border-width) solid ${contrastBorder};
386
- outline-offset: -1px;
387
- }
383
+ collector.addRule(`
384
+ .theia-scm-input-message-container textarea {
385
+ outline: var(--theia-border-width) solid ${contrastBorder};
386
+ outline-offset: -1px;
387
+ }
388
388
  `);
389
389
  }
390
390
  }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@theia/scm",
3
- "version": "1.53.0-next.5+1e5fb536d",
3
+ "version": "1.53.0-next.55+d1a989a68c",
4
4
  "description": "Theia - Source control Extension",
5
5
  "dependencies": {
6
- "@theia/core": "1.53.0-next.5+1e5fb536d",
7
- "@theia/editor": "1.53.0-next.5+1e5fb536d",
8
- "@theia/filesystem": "1.53.0-next.5+1e5fb536d",
9
- "@theia/monaco": "1.53.0-next.5+1e5fb536d",
6
+ "@theia/core": "1.53.0-next.55+d1a989a68c",
7
+ "@theia/editor": "1.53.0-next.55+d1a989a68c",
8
+ "@theia/filesystem": "1.53.0-next.55+d1a989a68c",
9
+ "@theia/monaco": "1.53.0-next.55+d1a989a68c",
10
10
  "@theia/monaco-editor-core": "1.83.101",
11
11
  "@types/diff": "^5.2.1",
12
12
  "diff": "^5.2.0",
@@ -49,10 +49,10 @@
49
49
  "watch": "theiaext watch"
50
50
  },
51
51
  "devDependencies": {
52
- "@theia/ext-scripts": "1.52.0"
52
+ "@theia/ext-scripts": "1.53.0"
53
53
  },
54
54
  "nyc": {
55
55
  "extends": "../../configs/nyc.json"
56
56
  },
57
- "gitHead": "1e5fb536d65550ad8fa0fefcec731645b2afc74a"
57
+ "gitHead": "d1a989a68c1b5ec1f9098e9126653c6346844769"
58
58
  }
@@ -1,102 +1,102 @@
1
- // *****************************************************************************
2
- // Copyright (C) 2019 Red Hat, Inc. and others.
3
- //
4
- // This program and the accompanying materials are made available under the
5
- // terms of the Eclipse Public License v. 2.0 which is available at
6
- // http://www.eclipse.org/legal/epl-2.0.
7
- //
8
- // This Source Code may also be made available under the following Secondary
9
- // Licenses when the conditions for such availability set forth in the Eclipse
10
- // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
- // with the GNU Classpath Exception which is available at
12
- // https://www.gnu.org/software/classpath/license.html.
13
- //
14
- // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
- // *****************************************************************************
16
-
17
- import { injectable, inject } from '@theia/core/shared/inversify';
18
- import { DisposableCollection, Emitter, Event, ResourceProvider } from '@theia/core';
19
- import { DirtyDiffDecorator, DirtyDiffUpdate } from '../dirty-diff/dirty-diff-decorator';
20
- import { DiffComputer } from '../dirty-diff/diff-computer';
21
- import { ContentLines } from '../dirty-diff/content-lines';
22
- import { EditorManager, EditorWidget, TextEditor } from '@theia/editor/lib/browser';
23
- import { ScmService } from '../scm-service';
24
-
25
- import throttle = require('@theia/core/shared/lodash.throttle');
26
-
27
- @injectable()
28
- export class ScmDecorationsService {
29
- private readonly diffComputer = new DiffComputer();
30
-
31
- protected readonly onDirtyDiffUpdateEmitter = new Emitter<DirtyDiffUpdate>();
32
- readonly onDirtyDiffUpdate: Event<DirtyDiffUpdate> = this.onDirtyDiffUpdateEmitter.event;
33
-
34
- constructor(
35
- @inject(DirtyDiffDecorator) protected readonly decorator: DirtyDiffDecorator,
36
- @inject(ScmService) protected readonly scmService: ScmService,
37
- @inject(EditorManager) protected readonly editorManager: EditorManager,
38
- @inject(ResourceProvider) protected readonly resourceProvider: ResourceProvider
39
- ) {
40
- const updateTasks = new Map<EditorWidget, { (): void; cancel(): void }>();
41
- this.editorManager.onCreated(editorWidget => {
42
- const { editor } = editorWidget;
43
- if (!this.supportsDirtyDiff(editor)) {
44
- return;
45
- }
46
- const toDispose = new DisposableCollection();
47
- const updateTask = this.createUpdateTask(editor);
48
- updateTasks.set(editorWidget, updateTask);
49
- toDispose.push(editor.onDocumentContentChanged(() => updateTask()));
50
- editorWidget.disposed.connect(() => {
51
- updateTask.cancel();
52
- updateTasks.delete(editorWidget);
53
- toDispose.dispose();
54
- });
55
- updateTask();
56
- });
57
- const runUpdateTasks = () => {
58
- for (const updateTask of updateTasks.values()) {
59
- updateTask();
60
- }
61
- };
62
- this.scmService.onDidAddRepository(({ provider }) => {
63
- provider.onDidChange(runUpdateTasks);
64
- provider.onDidChangeResources?.(runUpdateTasks);
65
- });
66
- this.scmService.onDidChangeSelectedRepository(runUpdateTasks);
67
- }
68
-
69
- async applyEditorDecorations(editor: TextEditor): Promise<void> {
70
- const currentRepo = this.scmService.selectedRepository;
71
- if (currentRepo) {
72
- try {
73
- // Currently, the uri used here is specific to vscode.git; other SCM providers are thus not supported.
74
- // See https://github.com/eclipse-theia/theia/pull/13104#discussion_r1494540628 for a detailed discussion.
75
- const query = { path: editor.uri['codeUri'].fsPath, ref: '~' };
76
- const uri = editor.uri.withScheme(currentRepo.provider.id).withQuery(JSON.stringify(query));
77
- const previousResource = await this.resourceProvider(uri);
78
- try {
79
- const previousContent = await previousResource.readContents();
80
- const previousLines = ContentLines.fromString(previousContent);
81
- const currentLines = ContentLines.fromTextEditorDocument(editor.document);
82
- const dirtyDiff = this.diffComputer.computeDirtyDiff(ContentLines.arrayLike(previousLines), ContentLines.arrayLike(currentLines));
83
- const update = <DirtyDiffUpdate>{ editor, previousRevisionUri: uri, ...dirtyDiff };
84
- this.decorator.applyDecorations(update);
85
- this.onDirtyDiffUpdateEmitter.fire(update);
86
- } finally {
87
- previousResource.dispose();
88
- }
89
- } catch (e) {
90
- // Scm resource may not be found, do nothing.
91
- }
92
- }
93
- }
94
-
95
- protected supportsDirtyDiff(editor: TextEditor): boolean {
96
- return editor.shouldDisplayDirtyDiff();
97
- }
98
-
99
- protected createUpdateTask(editor: TextEditor): { (): void; cancel(): void; } {
100
- return throttle(() => this.applyEditorDecorations(editor), 500);
101
- }
102
- }
1
+ // *****************************************************************************
2
+ // Copyright (C) 2019 Red Hat, Inc. and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { injectable, inject } from '@theia/core/shared/inversify';
18
+ import { DisposableCollection, Emitter, Event, ResourceProvider } from '@theia/core';
19
+ import { DirtyDiffDecorator, DirtyDiffUpdate } from '../dirty-diff/dirty-diff-decorator';
20
+ import { DiffComputer } from '../dirty-diff/diff-computer';
21
+ import { ContentLines } from '../dirty-diff/content-lines';
22
+ import { EditorManager, EditorWidget, TextEditor } from '@theia/editor/lib/browser';
23
+ import { ScmService } from '../scm-service';
24
+
25
+ import throttle = require('@theia/core/shared/lodash.throttle');
26
+
27
+ @injectable()
28
+ export class ScmDecorationsService {
29
+ private readonly diffComputer = new DiffComputer();
30
+
31
+ protected readonly onDirtyDiffUpdateEmitter = new Emitter<DirtyDiffUpdate>();
32
+ readonly onDirtyDiffUpdate: Event<DirtyDiffUpdate> = this.onDirtyDiffUpdateEmitter.event;
33
+
34
+ constructor(
35
+ @inject(DirtyDiffDecorator) protected readonly decorator: DirtyDiffDecorator,
36
+ @inject(ScmService) protected readonly scmService: ScmService,
37
+ @inject(EditorManager) protected readonly editorManager: EditorManager,
38
+ @inject(ResourceProvider) protected readonly resourceProvider: ResourceProvider
39
+ ) {
40
+ const updateTasks = new Map<EditorWidget, { (): void; cancel(): void }>();
41
+ this.editorManager.onCreated(editorWidget => {
42
+ const { editor } = editorWidget;
43
+ if (!this.supportsDirtyDiff(editor)) {
44
+ return;
45
+ }
46
+ const toDispose = new DisposableCollection();
47
+ const updateTask = this.createUpdateTask(editor);
48
+ updateTasks.set(editorWidget, updateTask);
49
+ toDispose.push(editor.onDocumentContentChanged(() => updateTask()));
50
+ editorWidget.disposed.connect(() => {
51
+ updateTask.cancel();
52
+ updateTasks.delete(editorWidget);
53
+ toDispose.dispose();
54
+ });
55
+ updateTask();
56
+ });
57
+ const runUpdateTasks = () => {
58
+ for (const updateTask of updateTasks.values()) {
59
+ updateTask();
60
+ }
61
+ };
62
+ this.scmService.onDidAddRepository(({ provider }) => {
63
+ provider.onDidChange(runUpdateTasks);
64
+ provider.onDidChangeResources?.(runUpdateTasks);
65
+ });
66
+ this.scmService.onDidChangeSelectedRepository(runUpdateTasks);
67
+ }
68
+
69
+ async applyEditorDecorations(editor: TextEditor): Promise<void> {
70
+ const currentRepo = this.scmService.selectedRepository;
71
+ if (currentRepo) {
72
+ try {
73
+ // Currently, the uri used here is specific to vscode.git; other SCM providers are thus not supported.
74
+ // See https://github.com/eclipse-theia/theia/pull/13104#discussion_r1494540628 for a detailed discussion.
75
+ const query = { path: editor.uri['codeUri'].fsPath, ref: '~' };
76
+ const uri = editor.uri.withScheme(currentRepo.provider.id).withQuery(JSON.stringify(query));
77
+ const previousResource = await this.resourceProvider(uri);
78
+ try {
79
+ const previousContent = await previousResource.readContents();
80
+ const previousLines = ContentLines.fromString(previousContent);
81
+ const currentLines = ContentLines.fromTextEditorDocument(editor.document);
82
+ const dirtyDiff = this.diffComputer.computeDirtyDiff(ContentLines.arrayLike(previousLines), ContentLines.arrayLike(currentLines));
83
+ const update = <DirtyDiffUpdate>{ editor, previousRevisionUri: uri, ...dirtyDiff };
84
+ this.decorator.applyDecorations(update);
85
+ this.onDirtyDiffUpdateEmitter.fire(update);
86
+ } finally {
87
+ previousResource.dispose();
88
+ }
89
+ } catch (e) {
90
+ // Scm resource may not be found, do nothing.
91
+ }
92
+ }
93
+ }
94
+
95
+ protected supportsDirtyDiff(editor: TextEditor): boolean {
96
+ return editor.shouldDisplayDirtyDiff();
97
+ }
98
+
99
+ protected createUpdateTask(editor: TextEditor): { (): void; cancel(): void; } {
100
+ return throttle(() => this.applyEditorDecorations(editor), 500);
101
+ }
102
+ }
@@ -1,121 +1,121 @@
1
- // *****************************************************************************
2
- // Copyright (C) 2019 Red Hat, Inc. and others.
3
- //
4
- // This program and the accompanying materials are made available under the
5
- // terms of the Eclipse Public License v. 2.0 which is available at
6
- // http://www.eclipse.org/legal/epl-2.0.
7
- //
8
- // This Source Code may also be made available under the following Secondary
9
- // Licenses when the conditions for such availability set forth in the Eclipse
10
- // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
- // with the GNU Classpath Exception which is available at
12
- // https://www.gnu.org/software/classpath/license.html.
13
- //
14
- // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
- // *****************************************************************************
16
-
17
- import { inject, injectable } from '@theia/core/shared/inversify';
18
- import { ILogger } from '@theia/core/lib/common/logger';
19
- import { Event, Emitter } from '@theia/core/lib/common/event';
20
- import { Tree } from '@theia/core/lib/browser/tree/tree';
21
- import { TreeDecorator, TreeDecoration } from '@theia/core/lib/browser/tree/tree-decorator';
22
- import { DepthFirstTreeIterator } from '@theia/core/lib/browser';
23
- import { FileStatNode } from '@theia/filesystem/lib/browser';
24
- import URI from '@theia/core/lib/common/uri';
25
- import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
26
- import { Decoration, DecorationsService } from '@theia/core/lib/browser/decorations-service';
27
-
28
- /**
29
- * @deprecated since 1.25.0
30
- * URI-based decorators should implement `DecorationsProvider` and contribute decorations via the `DecorationsService`.
31
- */
32
- @injectable()
33
- export class ScmNavigatorDecorator implements TreeDecorator {
34
-
35
- readonly id = 'theia-scm-decorator';
36
- private decorationsMap: Map<string, Decoration> | undefined;
37
-
38
- @inject(ILogger) protected readonly logger: ILogger;
39
-
40
- @inject(ColorRegistry)
41
- protected readonly colors: ColorRegistry;
42
-
43
- constructor(@inject(DecorationsService) protected readonly decorationsService: DecorationsService) {
44
- this.decorationsService.onDidChangeDecorations(data => {
45
- this.decorationsMap = data;
46
- this.fireDidChangeDecorations((tree: Tree) => this.collectDecorators(tree));
47
- });
48
- }
49
-
50
- protected collectDecorators(tree: Tree): Map<string, TreeDecoration.Data> {
51
- const result = new Map();
52
- if (tree.root === undefined || !this.decorationsMap) {
53
- return result;
54
- }
55
- const markers = this.appendContainerChanges(this.decorationsMap);
56
- for (const treeNode of new DepthFirstTreeIterator(tree.root)) {
57
- const uri = FileStatNode.getUri(treeNode);
58
- if (uri) {
59
- const marker = markers.get(uri);
60
- if (marker) {
61
- result.set(treeNode.id, marker);
62
- }
63
- }
64
- }
65
- return new Map(Array.from(result.entries()).map(m => [m[0], this.toDecorator(m[1])] as [string, TreeDecoration.Data]));
66
- }
67
-
68
- protected toDecorator(change: Decoration): TreeDecoration.Data {
69
- const colorVariable = change.colorId && this.colors.toCssVariableName(change.colorId);
70
- return {
71
- tailDecorations: [
72
- {
73
- data: change.letter ? change.letter : '',
74
- fontData: {
75
- color: colorVariable && `var(${colorVariable})`
76
- },
77
- tooltip: change.tooltip ? change.tooltip : ''
78
- }
79
- ]
80
- };
81
- }
82
-
83
- protected readonly emitter = new Emitter<(tree: Tree) => Map<string, TreeDecoration.Data>>();
84
-
85
- async decorations(tree: Tree): Promise<Map<string, TreeDecoration.Data>> {
86
- if (this.decorationsMap) {
87
- return this.collectDecorators(tree);
88
- } else {
89
- return new Map();
90
- }
91
- }
92
-
93
- protected appendContainerChanges(decorationsMap: Map<string, Decoration>): Map<string, Decoration> {
94
- const result: Map<string, Decoration> = new Map();
95
- for (const [uri, data] of decorationsMap.entries()) {
96
- const uriString = uri.toString();
97
- result.set(uriString, data);
98
- let parentUri: URI | undefined = new URI(uri).parent;
99
- while (parentUri && !parentUri.path.isRoot) {
100
- const parentUriString = parentUri.toString();
101
- const existing = result.get(parentUriString);
102
- if (existing === undefined) {
103
- result.set(parentUriString, data);
104
- parentUri = parentUri.parent;
105
- } else {
106
- parentUri = undefined;
107
- }
108
- }
109
- }
110
- return result;
111
- }
112
-
113
- get onDidChangeDecorations(): Event<(tree: Tree) => Map<string, TreeDecoration.Data>> {
114
- return this.emitter.event;
115
- }
116
-
117
- fireDidChangeDecorations(event: (tree: Tree) => Map<string, TreeDecoration.Data>): void {
118
- this.emitter.fire(event);
119
- }
120
-
121
- }
1
+ // *****************************************************************************
2
+ // Copyright (C) 2019 Red Hat, Inc. and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { inject, injectable } from '@theia/core/shared/inversify';
18
+ import { ILogger } from '@theia/core/lib/common/logger';
19
+ import { Event, Emitter } from '@theia/core/lib/common/event';
20
+ import { Tree } from '@theia/core/lib/browser/tree/tree';
21
+ import { TreeDecorator, TreeDecoration } from '@theia/core/lib/browser/tree/tree-decorator';
22
+ import { DepthFirstTreeIterator } from '@theia/core/lib/browser';
23
+ import { FileStatNode } from '@theia/filesystem/lib/browser';
24
+ import URI from '@theia/core/lib/common/uri';
25
+ import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
26
+ import { Decoration, DecorationsService } from '@theia/core/lib/browser/decorations-service';
27
+
28
+ /**
29
+ * @deprecated since 1.25.0
30
+ * URI-based decorators should implement `DecorationsProvider` and contribute decorations via the `DecorationsService`.
31
+ */
32
+ @injectable()
33
+ export class ScmNavigatorDecorator implements TreeDecorator {
34
+
35
+ readonly id = 'theia-scm-decorator';
36
+ private decorationsMap: Map<string, Decoration> | undefined;
37
+
38
+ @inject(ILogger) protected readonly logger: ILogger;
39
+
40
+ @inject(ColorRegistry)
41
+ protected readonly colors: ColorRegistry;
42
+
43
+ constructor(@inject(DecorationsService) protected readonly decorationsService: DecorationsService) {
44
+ this.decorationsService.onDidChangeDecorations(data => {
45
+ this.decorationsMap = data;
46
+ this.fireDidChangeDecorations((tree: Tree) => this.collectDecorators(tree));
47
+ });
48
+ }
49
+
50
+ protected collectDecorators(tree: Tree): Map<string, TreeDecoration.Data> {
51
+ const result = new Map();
52
+ if (tree.root === undefined || !this.decorationsMap) {
53
+ return result;
54
+ }
55
+ const markers = this.appendContainerChanges(this.decorationsMap);
56
+ for (const treeNode of new DepthFirstTreeIterator(tree.root)) {
57
+ const uri = FileStatNode.getUri(treeNode);
58
+ if (uri) {
59
+ const marker = markers.get(uri);
60
+ if (marker) {
61
+ result.set(treeNode.id, marker);
62
+ }
63
+ }
64
+ }
65
+ return new Map(Array.from(result.entries()).map(m => [m[0], this.toDecorator(m[1])] as [string, TreeDecoration.Data]));
66
+ }
67
+
68
+ protected toDecorator(change: Decoration): TreeDecoration.Data {
69
+ const colorVariable = change.colorId && this.colors.toCssVariableName(change.colorId);
70
+ return {
71
+ tailDecorations: [
72
+ {
73
+ data: change.letter ? change.letter : '',
74
+ fontData: {
75
+ color: colorVariable && `var(${colorVariable})`
76
+ },
77
+ tooltip: change.tooltip ? change.tooltip : ''
78
+ }
79
+ ]
80
+ };
81
+ }
82
+
83
+ protected readonly emitter = new Emitter<(tree: Tree) => Map<string, TreeDecoration.Data>>();
84
+
85
+ async decorations(tree: Tree): Promise<Map<string, TreeDecoration.Data>> {
86
+ if (this.decorationsMap) {
87
+ return this.collectDecorators(tree);
88
+ } else {
89
+ return new Map();
90
+ }
91
+ }
92
+
93
+ protected appendContainerChanges(decorationsMap: Map<string, Decoration>): Map<string, Decoration> {
94
+ const result: Map<string, Decoration> = new Map();
95
+ for (const [uri, data] of decorationsMap.entries()) {
96
+ const uriString = uri.toString();
97
+ result.set(uriString, data);
98
+ let parentUri: URI | undefined = new URI(uri).parent;
99
+ while (parentUri && !parentUri.path.isRoot) {
100
+ const parentUriString = parentUri.toString();
101
+ const existing = result.get(parentUriString);
102
+ if (existing === undefined) {
103
+ result.set(parentUriString, data);
104
+ parentUri = parentUri.parent;
105
+ } else {
106
+ parentUri = undefined;
107
+ }
108
+ }
109
+ }
110
+ return result;
111
+ }
112
+
113
+ get onDidChangeDecorations(): Event<(tree: Tree) => Map<string, TreeDecoration.Data>> {
114
+ return this.emitter.event;
115
+ }
116
+
117
+ fireDidChangeDecorations(event: (tree: Tree) => Map<string, TreeDecoration.Data>): void {
118
+ this.emitter.fire(event);
119
+ }
120
+
121
+ }