@theia/scm 1.48.2 → 1.49.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.
- package/lib/browser/decorations/scm-decorations-service.d.ts +9 -3
- package/lib/browser/decorations/scm-decorations-service.d.ts.map +1 -1
- package/lib/browser/decorations/scm-decorations-service.js +50 -30
- package/lib/browser/decorations/scm-decorations-service.js.map +1 -1
- package/lib/browser/dirty-diff/content-lines.d.ts +2 -0
- package/lib/browser/dirty-diff/content-lines.d.ts.map +1 -1
- package/lib/browser/dirty-diff/content-lines.js +7 -0
- package/lib/browser/dirty-diff/content-lines.js.map +1 -1
- package/lib/browser/dirty-diff/diff-computer.d.ts +23 -14
- package/lib/browser/dirty-diff/diff-computer.d.ts.map +1 -1
- package/lib/browser/dirty-diff/diff-computer.js +91 -27
- package/lib/browser/dirty-diff/diff-computer.js.map +1 -1
- package/lib/browser/dirty-diff/diff-computer.spec.js +120 -52
- package/lib/browser/dirty-diff/diff-computer.spec.js.map +1 -1
- package/lib/browser/dirty-diff/dirty-diff-decorator.d.ts +5 -3
- package/lib/browser/dirty-diff/dirty-diff-decorator.d.ts.map +1 -1
- package/lib/browser/dirty-diff/dirty-diff-decorator.js +14 -7
- package/lib/browser/dirty-diff/dirty-diff-decorator.js.map +1 -1
- package/lib/browser/dirty-diff/dirty-diff-module.d.ts.map +1 -1
- package/lib/browser/dirty-diff/dirty-diff-module.js +9 -0
- package/lib/browser/dirty-diff/dirty-diff-module.js.map +1 -1
- package/lib/browser/dirty-diff/dirty-diff-navigator.d.ts +49 -0
- package/lib/browser/dirty-diff/dirty-diff-navigator.d.ts.map +1 -0
- package/lib/browser/dirty-diff/dirty-diff-navigator.js +292 -0
- package/lib/browser/dirty-diff/dirty-diff-navigator.js.map +1 -0
- package/lib/browser/dirty-diff/dirty-diff-widget.d.ts +47 -0
- package/lib/browser/dirty-diff/dirty-diff-widget.d.ts.map +1 -0
- package/lib/browser/dirty-diff/dirty-diff-widget.js +320 -0
- package/lib/browser/dirty-diff/dirty-diff-widget.js.map +1 -0
- package/lib/browser/scm-colors.d.ts +6 -0
- package/lib/browser/scm-colors.d.ts.map +1 -0
- package/lib/browser/scm-colors.js +25 -0
- package/lib/browser/scm-colors.js.map +1 -0
- package/lib/browser/scm-contribution.d.ts +20 -6
- package/lib/browser/scm-contribution.d.ts.map +1 -1
- package/lib/browser/scm-contribution.js +112 -22
- package/lib/browser/scm-contribution.js.map +1 -1
- package/lib/browser/scm-tree-widget.js +1 -1
- package/lib/browser/scm-tree-widget.js.map +1 -1
- package/package.json +8 -6
- package/src/browser/decorations/scm-decorations-service.ts +60 -36
- package/src/browser/dirty-diff/content-lines.ts +9 -0
- package/src/browser/dirty-diff/diff-computer.spec.ts +120 -52
- package/src/browser/dirty-diff/diff-computer.ts +88 -40
- package/src/browser/dirty-diff/dirty-diff-decorator.ts +17 -10
- package/src/browser/dirty-diff/dirty-diff-module.ts +9 -0
- package/src/browser/dirty-diff/dirty-diff-navigator.ts +288 -0
- package/src/browser/dirty-diff/dirty-diff-widget.ts +364 -0
- package/src/browser/scm-colors.ts +21 -0
- package/src/browser/scm-contribution.ts +97 -6
- package/src/browser/scm-tree-widget.tsx +1 -1
- package/src/browser/style/dirty-diff-decorator.css +2 -1
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
CssStyleCollector
|
|
30
30
|
} from '@theia/core/lib/browser';
|
|
31
31
|
import { TabBarToolbarContribution, TabBarToolbarRegistry, TabBarToolbarItem } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
|
32
|
-
import { CommandRegistry, Command, Disposable, DisposableCollection, CommandService } from '@theia/core/lib/common';
|
|
32
|
+
import { CommandRegistry, Command, Disposable, DisposableCollection, CommandService, MenuModelRegistry } from '@theia/core/lib/common';
|
|
33
33
|
import { ContextKeyService, ContextKey } from '@theia/core/lib/browser/context-key-service';
|
|
34
34
|
import { ScmService } from './scm-service';
|
|
35
35
|
import { ScmWidget } from '../browser/scm-widget';
|
|
@@ -38,10 +38,13 @@ import { ScmQuickOpenService } from './scm-quick-open-service';
|
|
|
38
38
|
import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution';
|
|
39
39
|
import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
|
|
40
40
|
import { Color } from '@theia/core/lib/common/color';
|
|
41
|
+
import { ScmColors } from './scm-colors';
|
|
41
42
|
import { ScmCommand } from './scm-provider';
|
|
42
43
|
import { ScmDecorationsService } from '../browser/decorations/scm-decorations-service';
|
|
43
44
|
import { nls } from '@theia/core/lib/common/nls';
|
|
44
45
|
import { isHighContrast } from '@theia/core/lib/common/theme';
|
|
46
|
+
import { EditorMainMenu } from '@theia/editor/lib/browser';
|
|
47
|
+
import { DirtyDiffNavigator } from './dirty-diff/dirty-diff-navigator';
|
|
45
48
|
|
|
46
49
|
export const SCM_WIDGET_FACTORY_ID = ScmWidget.ID;
|
|
47
50
|
export const SCM_VIEW_CONTAINER_ID = 'scm-view-container';
|
|
@@ -51,6 +54,10 @@ export const SCM_VIEW_CONTAINER_TITLE_OPTIONS: ViewContainerTitleOptions = {
|
|
|
51
54
|
closeable: true
|
|
52
55
|
};
|
|
53
56
|
|
|
57
|
+
export namespace ScmMenus {
|
|
58
|
+
export const CHANGES_GROUP = [...EditorMainMenu.GO, '6_changes_group'];
|
|
59
|
+
}
|
|
60
|
+
|
|
54
61
|
export namespace SCM_COMMANDS {
|
|
55
62
|
export const CHANGE_REPOSITORY = {
|
|
56
63
|
id: 'scm.change.repository',
|
|
@@ -85,13 +92,36 @@ export namespace SCM_COMMANDS {
|
|
|
85
92
|
label: nls.localizeByDefault('Collapse All'),
|
|
86
93
|
originalLabel: 'Collapse All'
|
|
87
94
|
};
|
|
95
|
+
export const GOTO_NEXT_CHANGE = Command.toDefaultLocalizedCommand({
|
|
96
|
+
id: 'workbench.action.editor.nextChange',
|
|
97
|
+
category: 'Source Control',
|
|
98
|
+
label: 'Go to Next Change'
|
|
99
|
+
});
|
|
100
|
+
export const GOTO_PREVIOUS_CHANGE = Command.toDefaultLocalizedCommand({
|
|
101
|
+
id: 'workbench.action.editor.previousChange',
|
|
102
|
+
category: 'Source Control',
|
|
103
|
+
label: 'Go to Previous Change'
|
|
104
|
+
});
|
|
105
|
+
export const SHOW_NEXT_CHANGE = Command.toDefaultLocalizedCommand({
|
|
106
|
+
id: 'editor.action.dirtydiff.next',
|
|
107
|
+
category: 'Source Control',
|
|
108
|
+
label: 'Show Next Change'
|
|
109
|
+
});
|
|
110
|
+
export const SHOW_PREVIOUS_CHANGE = Command.toDefaultLocalizedCommand({
|
|
111
|
+
id: 'editor.action.dirtydiff.previous',
|
|
112
|
+
category: 'Source Control',
|
|
113
|
+
label: 'Show Previous Change'
|
|
114
|
+
});
|
|
115
|
+
export const CLOSE_CHANGE_PEEK_VIEW = {
|
|
116
|
+
id: 'editor.action.dirtydiff.close',
|
|
117
|
+
category: nls.localizeByDefault('Source Control'),
|
|
118
|
+
originalCategory: 'Source Control',
|
|
119
|
+
label: nls.localize('theia/scm/dirtyDiff/close', 'Close Change Peek View'),
|
|
120
|
+
originalLabel: 'Close Change Peek View'
|
|
121
|
+
};
|
|
88
122
|
}
|
|
89
123
|
|
|
90
|
-
export
|
|
91
|
-
export const editorGutterModifiedBackground = 'editorGutter.modifiedBackground';
|
|
92
|
-
export const editorGutterAddedBackground = 'editorGutter.addedBackground';
|
|
93
|
-
export const editorGutterDeletedBackground = 'editorGutter.deletedBackground';
|
|
94
|
-
}
|
|
124
|
+
export { ScmColors };
|
|
95
125
|
|
|
96
126
|
@injectable()
|
|
97
127
|
export class ScmContribution extends AbstractViewContribution<ScmWidget> implements
|
|
@@ -108,6 +138,7 @@ export class ScmContribution extends AbstractViewContribution<ScmWidget> impleme
|
|
|
108
138
|
@inject(CommandRegistry) protected readonly commandRegistry: CommandRegistry;
|
|
109
139
|
@inject(ContextKeyService) protected readonly contextKeys: ContextKeyService;
|
|
110
140
|
@inject(ScmDecorationsService) protected readonly scmDecorationsService: ScmDecorationsService;
|
|
141
|
+
@inject(DirtyDiffNavigator) protected readonly dirtyDiffNavigator: DirtyDiffNavigator;
|
|
111
142
|
|
|
112
143
|
protected scmFocus: ContextKey<boolean>;
|
|
113
144
|
|
|
@@ -144,6 +175,8 @@ export class ScmContribution extends AbstractViewContribution<ScmWidget> impleme
|
|
|
144
175
|
|
|
145
176
|
this.updateContextKeys();
|
|
146
177
|
this.shell.onDidChangeCurrentWidget(() => this.updateContextKeys());
|
|
178
|
+
|
|
179
|
+
this.scmDecorationsService.onDirtyDiffUpdate(update => this.dirtyDiffNavigator.handleDirtyDiffUpdate(update));
|
|
147
180
|
}
|
|
148
181
|
|
|
149
182
|
protected updateContextKeys(): void {
|
|
@@ -160,6 +193,39 @@ export class ScmContribution extends AbstractViewContribution<ScmWidget> impleme
|
|
|
160
193
|
execute: () => this.acceptInput(),
|
|
161
194
|
isEnabled: () => !!this.scmFocus.get() && !!this.acceptInputCommand()
|
|
162
195
|
});
|
|
196
|
+
|
|
197
|
+
// Note that commands for dirty diff navigation need to be always available.
|
|
198
|
+
// This is consistent with behavior in VS Code, and also with other similar commands (such as `Next Problem/Previous Problem`) in Theia.
|
|
199
|
+
// See https://github.com/eclipse-theia/theia/pull/13104#discussion_r1497316614 for a detailed discussion.
|
|
200
|
+
commandRegistry.registerCommand(SCM_COMMANDS.GOTO_NEXT_CHANGE, {
|
|
201
|
+
execute: () => this.dirtyDiffNavigator.gotoNextChange()
|
|
202
|
+
});
|
|
203
|
+
commandRegistry.registerCommand(SCM_COMMANDS.GOTO_PREVIOUS_CHANGE, {
|
|
204
|
+
execute: () => this.dirtyDiffNavigator.gotoPreviousChange()
|
|
205
|
+
});
|
|
206
|
+
commandRegistry.registerCommand(SCM_COMMANDS.SHOW_NEXT_CHANGE, {
|
|
207
|
+
execute: () => this.dirtyDiffNavigator.showNextChange()
|
|
208
|
+
});
|
|
209
|
+
commandRegistry.registerCommand(SCM_COMMANDS.SHOW_PREVIOUS_CHANGE, {
|
|
210
|
+
execute: () => this.dirtyDiffNavigator.showPreviousChange()
|
|
211
|
+
});
|
|
212
|
+
commandRegistry.registerCommand(SCM_COMMANDS.CLOSE_CHANGE_PEEK_VIEW, {
|
|
213
|
+
execute: () => this.dirtyDiffNavigator.closeChangePeekView()
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
override registerMenus(menus: MenuModelRegistry): void {
|
|
218
|
+
super.registerMenus(menus);
|
|
219
|
+
menus.registerMenuAction(ScmMenus.CHANGES_GROUP, {
|
|
220
|
+
commandId: SCM_COMMANDS.SHOW_NEXT_CHANGE.id,
|
|
221
|
+
label: nls.localizeByDefault('Next Change'),
|
|
222
|
+
order: '1'
|
|
223
|
+
});
|
|
224
|
+
menus.registerMenuAction(ScmMenus.CHANGES_GROUP, {
|
|
225
|
+
commandId: SCM_COMMANDS.SHOW_PREVIOUS_CHANGE.id,
|
|
226
|
+
label: nls.localizeByDefault('Previous Change'),
|
|
227
|
+
order: '2'
|
|
228
|
+
});
|
|
163
229
|
}
|
|
164
230
|
|
|
165
231
|
registerToolbarItems(registry: TabBarToolbarRegistry): void {
|
|
@@ -219,6 +285,31 @@ export class ScmContribution extends AbstractViewContribution<ScmWidget> impleme
|
|
|
219
285
|
keybinding: 'ctrlcmd+enter',
|
|
220
286
|
when: 'scmFocus'
|
|
221
287
|
});
|
|
288
|
+
keybindings.registerKeybinding({
|
|
289
|
+
command: SCM_COMMANDS.GOTO_NEXT_CHANGE.id,
|
|
290
|
+
keybinding: 'alt+f5',
|
|
291
|
+
when: 'editorTextFocus'
|
|
292
|
+
});
|
|
293
|
+
keybindings.registerKeybinding({
|
|
294
|
+
command: SCM_COMMANDS.GOTO_PREVIOUS_CHANGE.id,
|
|
295
|
+
keybinding: 'shift+alt+f5',
|
|
296
|
+
when: 'editorTextFocus'
|
|
297
|
+
});
|
|
298
|
+
keybindings.registerKeybinding({
|
|
299
|
+
command: SCM_COMMANDS.SHOW_NEXT_CHANGE.id,
|
|
300
|
+
keybinding: 'alt+f3',
|
|
301
|
+
when: 'editorTextFocus'
|
|
302
|
+
});
|
|
303
|
+
keybindings.registerKeybinding({
|
|
304
|
+
command: SCM_COMMANDS.SHOW_PREVIOUS_CHANGE.id,
|
|
305
|
+
keybinding: 'shift+alt+f3',
|
|
306
|
+
when: 'editorTextFocus'
|
|
307
|
+
});
|
|
308
|
+
keybindings.registerKeybinding({
|
|
309
|
+
command: SCM_COMMANDS.CLOSE_CHANGE_PEEK_VIEW.id,
|
|
310
|
+
keybinding: 'esc',
|
|
311
|
+
when: 'dirtyDiffVisible'
|
|
312
|
+
});
|
|
222
313
|
}
|
|
223
314
|
|
|
224
315
|
protected async acceptInput(): Promise<void> {
|
|
@@ -605,7 +605,7 @@ export class ScmResourceComponent extends ScmElement<ScmResourceComponent.Props>
|
|
|
605
605
|
|
|
606
606
|
protected readonly contextMenuPath = ScmTreeWidget.RESOURCE_CONTEXT_MENU;
|
|
607
607
|
protected get contextMenuArgs(): any[] {
|
|
608
|
-
if (!this.props.model.selectedNodes.some(node => ScmFileChangeNode.is(node) && node
|
|
608
|
+
if (!this.props.model.selectedNodes.some(node => ScmFileChangeNode.is(node) && node === this.props.treeNode)) {
|
|
609
609
|
// Clicked node is not in selection, so ignore selection and action on just clicked node
|
|
610
610
|
return this.singleNodeArgs;
|
|
611
611
|
} else {
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
border-top: 4px solid transparent;
|
|
20
20
|
border-bottom: 4px solid transparent;
|
|
21
21
|
transition: border-top-width 80ms linear, border-bottom-width 80ms linear, bottom 80ms linear;
|
|
22
|
+
pointer-events: none;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
.dirty-diff-glyph:before {
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
position: absolute;
|
|
42
43
|
content: '';
|
|
43
44
|
height: 100%;
|
|
44
|
-
width:
|
|
45
|
+
width: 6px;
|
|
45
46
|
left: -6px;
|
|
46
47
|
}
|
|
47
48
|
|