mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 04:49:35 +00:00
diff: inline actions
This commit is contained in:
parent
c5e3aace45
commit
7d729c9d17
|
@ -101,6 +101,24 @@
|
|||
"title": "%command.revertSelectedRanges%",
|
||||
"category": "Git"
|
||||
},
|
||||
{
|
||||
"command": "git.stageChange",
|
||||
"title": "%command.stageChange%",
|
||||
"category": "Git",
|
||||
"icon": {
|
||||
"light": "resources/icons/light/stage.svg",
|
||||
"dark": "resources/icons/dark/stage.svg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "git.revertChange",
|
||||
"title": "%command.revertChange%",
|
||||
"category": "Git",
|
||||
"icon": {
|
||||
"light": "resources/icons/light/clean.svg",
|
||||
"dark": "resources/icons/dark/clean.svg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "git.unstage",
|
||||
"title": "%command.unstage%",
|
||||
|
@ -722,6 +740,16 @@
|
|||
"group": "2_git@3",
|
||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme != merge-conflict.conflict-diff"
|
||||
}
|
||||
],
|
||||
"scm/change/title": [
|
||||
{
|
||||
"command": "git.stageChange",
|
||||
"when": "config.git.enabled && originalResourceScheme == git"
|
||||
},
|
||||
{
|
||||
"command": "git.revertChange",
|
||||
"when": "config.git.enabled && originalResourceScheme == git"
|
||||
}
|
||||
]
|
||||
},
|
||||
"configuration": {
|
||||
|
@ -836,4 +864,4 @@
|
|||
"@types/node": "7.0.43",
|
||||
"mocha": "^3.2.0"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,8 @@
|
|||
"command.stageAll": "Stage All Changes",
|
||||
"command.stageSelectedRanges": "Stage Selected Ranges",
|
||||
"command.revertSelectedRanges": "Revert Selected Ranges",
|
||||
"command.stageChange": "Stage Change",
|
||||
"command.revertChange": "Revert Change",
|
||||
"command.unstage": "Unstage Changes",
|
||||
"command.unstageAll": "Unstage All Changes",
|
||||
"command.unstageSelectedRanges": "Unstage Selected Ranges",
|
||||
|
|
|
@ -556,8 +556,13 @@ export class CommandCenter {
|
|||
await repository.add([]);
|
||||
}
|
||||
|
||||
@command('git.stageChange')
|
||||
async stageChange(change: LineChange): Promise<void> {
|
||||
await this.stageChanges([change]);
|
||||
}
|
||||
|
||||
@command('git.stageSelectedRanges', { diff: true })
|
||||
async stageSelectedRanges(diffs: LineChange[]): Promise<void> {
|
||||
async stageChanges(changes: LineChange[]): Promise<void> {
|
||||
const textEditor = window.activeTextEditor;
|
||||
|
||||
if (!textEditor) {
|
||||
|
@ -574,7 +579,7 @@ export class CommandCenter {
|
|||
const originalUri = toGitUri(modifiedUri, '~');
|
||||
const originalDocument = await workspace.openTextDocument(originalUri);
|
||||
const selectedLines = toLineRanges(textEditor.selections, modifiedDocument);
|
||||
const selectedDiffs = diffs
|
||||
const selectedDiffs = changes
|
||||
.map(diff => selectedLines.reduce<LineChange | null>((result, range) => result || intersectDiffWithRange(modifiedDocument, diff, range), null))
|
||||
.filter(d => !!d) as LineChange[];
|
||||
|
||||
|
@ -587,8 +592,13 @@ export class CommandCenter {
|
|||
await this.runByRepository(modifiedUri, async (repository, resource) => await repository.stage(resource, result));
|
||||
}
|
||||
|
||||
@command('git.revertChange')
|
||||
async revertChange(change: LineChange): Promise<void> {
|
||||
await this.revertChanges([change]);
|
||||
}
|
||||
|
||||
@command('git.revertSelectedRanges', { diff: true })
|
||||
async revertSelectedRanges(diffs: LineChange[]): Promise<void> {
|
||||
async revertChanges(diffs: LineChange[]): Promise<void> {
|
||||
const textEditor = window.activeTextEditor;
|
||||
|
||||
if (!textEditor) {
|
||||
|
|
|
@ -39,20 +39,23 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
.monaco-editor .peekview-widget .head .peekview-actions > .monaco-action-bar .action-item {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.monaco-editor .peekview-widget .head .peekview-actions > .monaco-action-bar .action-label {
|
||||
width: 16px;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
line-height: inherit;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.monaco-editor .peekview-widget .head .peekview-actions > .monaco-action-bar .action-label.octicon {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.monaco-editor .peekview-widget .head .peekview-actions .action-label {
|
||||
width: 16px;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.monaco-editor .peekview-widget .head .peekview-actions .action-label.icon.close-peekview-action {
|
||||
background: url('close.svg') center center no-repeat;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ export class MenuId {
|
|||
static readonly SCMSourceControl = new MenuId();
|
||||
static readonly SCMResourceGroupContext = new MenuId();
|
||||
static readonly SCMResourceContext = new MenuId();
|
||||
static readonly SCMChangeContext = new MenuId();
|
||||
static readonly CommandPalette = new MenuId();
|
||||
static readonly ViewTitle = new MenuId();
|
||||
static readonly ViewItemContext = new MenuId();
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace schema {
|
|||
case 'scm/sourceControl': return MenuId.SCMSourceControl;
|
||||
case 'scm/resourceGroup/context': return MenuId.SCMResourceGroupContext;
|
||||
case 'scm/resourceState/context': return MenuId.SCMResourceContext;
|
||||
case 'scm/change/title': return MenuId.SCMChangeContext;
|
||||
case 'view/title': return MenuId.ViewTitle;
|
||||
case 'view/item/context': return MenuId.ViewItemContext;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import * as ext from 'vs/workbench/common/contributions';
|
|||
import * as common from 'vs/editor/common/editorCommon';
|
||||
import { CodeEditor } from 'vs/editor/browser/codeEditor';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IMessageService } from 'vs/platform/message/common/message';
|
||||
import { IMessageService, Severity } from 'vs/platform/message/common/message';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
@ -43,10 +43,27 @@ import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRe
|
|||
import { peekViewBorder, peekViewTitleBackground, peekViewTitleForeground, peekViewTitleInfoForeground } from 'vs/editor/contrib/referenceSearch/browser/referencesWidget';
|
||||
import { EmbeddedDiffEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget';
|
||||
import { IDiffEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IActionBarOptions, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { IActionBarOptions, ActionsOrientation, IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { basename } from 'vs/base/common/paths';
|
||||
import { MenuId, IMenuService, IMenu, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { fillInActions, MenuItemActionItem } from 'vs/platform/actions/browser/menuItemActionItem';
|
||||
|
||||
// TODO@Joao
|
||||
// Need to subclass MenuItemActionItem in order to respect
|
||||
// the action context coming from any action bar, without breaking
|
||||
// existing users
|
||||
class DiffMenuItemActionItem extends MenuItemActionItem {
|
||||
|
||||
onClick(event: MouseEvent): void {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
this.actionRunner.run(this._commandAction, this._context)
|
||||
.done(undefined, err => this._messageService.show(Severity.Error, err));
|
||||
}
|
||||
}
|
||||
|
||||
export interface IModelRegistry {
|
||||
getModel(editorModel: common.IEditorModel): DirtyDiffModel;
|
||||
|
@ -115,22 +132,31 @@ class DirtyDiffWidget extends PeekViewWidget {
|
|||
|
||||
private diffEditor: EmbeddedDiffEditorWidget;
|
||||
private title: string;
|
||||
private menu: IMenu;
|
||||
private change: common.IChange;
|
||||
private didLayout = false;
|
||||
private contextKeyService: IContextKeyService;
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
private model: DirtyDiffModel,
|
||||
themeService: IThemeService,
|
||||
private instantiationService: IInstantiationService
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IMenuService private menuService: IMenuService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService,
|
||||
@IMessageService private messageService: IMessageService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
) {
|
||||
super(editor, { isResizeable: true });
|
||||
|
||||
themeService.onThemeChange(this._applyTheme, this, this._disposables);
|
||||
this._applyTheme(themeService.getTheme());
|
||||
|
||||
this.create();
|
||||
this.contextKeyService = contextKeyService.createScoped();
|
||||
this.contextKeyService.createKey('originalResourceScheme', this.model.original.uri.scheme);
|
||||
this.menu = menuService.createMenu(MenuId.SCMChangeContext, this.contextKeyService);
|
||||
|
||||
this.create();
|
||||
this.title = basename(editor.getModel().uri.fsPath);
|
||||
this.setTitle(this.title);
|
||||
}
|
||||
|
@ -161,7 +187,7 @@ class DirtyDiffWidget extends PeekViewWidget {
|
|||
: localize('change', "{0} of {1} change", index + 1, this.model.changes.length);
|
||||
|
||||
this.setTitle(this.title, detail);
|
||||
|
||||
this._actionbarWidget.context = change;
|
||||
this.show(position, height);
|
||||
}
|
||||
|
||||
|
@ -174,14 +200,27 @@ class DirtyDiffWidget extends PeekViewWidget {
|
|||
this._disposables.push(previous);
|
||||
this._disposables.push(next);
|
||||
this._actionbarWidget.push([previous, next], { label: false, icon: true });
|
||||
|
||||
const actions: IAction[] = [];
|
||||
fillInActions(this.menu, { shouldForwardArgs: true }, actions);
|
||||
this._actionbarWidget.push(actions, { label: false, icon: true });
|
||||
}
|
||||
|
||||
protected _getActionBarOptions(): IActionBarOptions {
|
||||
return {
|
||||
actionItemProvider: action => this.getActionItem(action),
|
||||
orientation: ActionsOrientation.HORIZONTAL_REVERSE
|
||||
};
|
||||
}
|
||||
|
||||
getActionItem(action: IAction): IActionItem {
|
||||
if (!(action instanceof MenuItemAction)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return new DiffMenuItemActionItem(action, this.keybindingService, this.messageService);
|
||||
}
|
||||
|
||||
protected _fillBody(container: HTMLElement): void {
|
||||
const options: IDiffEditorOptions = {
|
||||
scrollBeyondLastLine: true,
|
||||
|
@ -395,7 +434,7 @@ export class DirtyDiffController implements common.IEditorContribution {
|
|||
|
||||
this.changeIndex = -1;
|
||||
this.model = model;
|
||||
this.widget = new DirtyDiffWidget(this.editor, model, this.themeService, this.instantiationService);
|
||||
this.widget = this.instantiationService.createInstance(DirtyDiffWidget, this.editor, model);
|
||||
this.isDirtyDiffVisible.set(true);
|
||||
|
||||
// TODO react on model changes
|
||||
|
|
Loading…
Reference in a new issue