mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 04:49:35 +00:00
Git - move "Open Commit" command from core to the git extension (#202042)
* Initial implementation * Move the command to the git extension * Add missing enablement property
This commit is contained in:
parent
88a6ed6d9b
commit
891a17ab57
|
@ -24,7 +24,8 @@
|
||||||
"tabInputTextMerge",
|
"tabInputTextMerge",
|
||||||
"timeline",
|
"timeline",
|
||||||
"contribMergeEditorMenus",
|
"contribMergeEditorMenus",
|
||||||
"contribSourceControlInputBoxMenu"
|
"contribSourceControlInputBoxMenu",
|
||||||
|
"contribSourceControlHistoryItemMenu"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"Other"
|
"Other"
|
||||||
|
@ -708,7 +709,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.timeline.openCommit",
|
"command": "git.timeline.openCommit",
|
||||||
"title": "%command.timelineOpenCommit%",
|
"title": "%command.openCommit%",
|
||||||
"icon": "$(diff-multiple)",
|
"icon": "$(diff-multiple)",
|
||||||
"category": "Git"
|
"category": "Git"
|
||||||
},
|
},
|
||||||
|
@ -776,13 +777,22 @@
|
||||||
"command": "git.viewChanges",
|
"command": "git.viewChanges",
|
||||||
"title": "%command.viewChanges%",
|
"title": "%command.viewChanges%",
|
||||||
"icon": "$(diff-multiple)",
|
"icon": "$(diff-multiple)",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!operationInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.viewStagedChanges",
|
"command": "git.viewStagedChanges",
|
||||||
"title": "%command.viewStagedChanges%",
|
"title": "%command.viewStagedChanges%",
|
||||||
"icon": "$(diff-multiple)",
|
"icon": "$(diff-multiple)",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!operationInProgress"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "git.openCommit",
|
||||||
|
"title": "%command.openCommit%",
|
||||||
|
"icon": "$(diff-multiple)",
|
||||||
|
"category": "Git",
|
||||||
|
"enablement": "!operationInProgress"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"continueEditSession": [
|
"continueEditSession": [
|
||||||
|
@ -1274,6 +1284,10 @@
|
||||||
{
|
{
|
||||||
"command": "git.viewStagedChanges",
|
"command": "git.viewStagedChanges",
|
||||||
"when": "false"
|
"when": "false"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "git.openCommit",
|
||||||
|
"when": "false"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"scm/title": [
|
"scm/title": [
|
||||||
|
@ -1751,6 +1765,20 @@
|
||||||
"group": "1_modification@3"
|
"group": "1_modification@3"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"scm/incoming/historyItem/context": [
|
||||||
|
{
|
||||||
|
"command": "git.openCommit",
|
||||||
|
"when": "scmProvider == git && config.multiDiffEditor.experimental.enabled",
|
||||||
|
"group": "inline@1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scm/outgoing/historyItem/context": [
|
||||||
|
{
|
||||||
|
"command": "git.openCommit",
|
||||||
|
"when": "scmProvider == git && config.multiDiffEditor.experimental.enabled",
|
||||||
|
"group": "inline@1"
|
||||||
|
}
|
||||||
|
],
|
||||||
"editor/title": [
|
"editor/title": [
|
||||||
{
|
{
|
||||||
"command": "git.openFile",
|
"command": "git.openFile",
|
||||||
|
|
|
@ -106,7 +106,6 @@
|
||||||
"command.stashDropAll": "Drop All Stashes...",
|
"command.stashDropAll": "Drop All Stashes...",
|
||||||
"command.stashPreview": "Preview Stash...",
|
"command.stashPreview": "Preview Stash...",
|
||||||
"command.timelineOpenDiff": "Open Changes",
|
"command.timelineOpenDiff": "Open Changes",
|
||||||
"command.timelineOpenCommit": "Open Commit",
|
|
||||||
"command.timelineCopyCommitId": "Copy Commit ID",
|
"command.timelineCopyCommitId": "Copy Commit ID",
|
||||||
"command.timelineCopyCommitMessage": "Copy Commit Message",
|
"command.timelineCopyCommitMessage": "Copy Commit Message",
|
||||||
"command.timelineSelectForCompare": "Select for Compare",
|
"command.timelineSelectForCompare": "Select for Compare",
|
||||||
|
@ -115,6 +114,7 @@
|
||||||
"command.openRepositoriesInParentFolders": "Open Repositories In Parent Folders",
|
"command.openRepositoriesInParentFolders": "Open Repositories In Parent Folders",
|
||||||
"command.viewChanges": "View Changes",
|
"command.viewChanges": "View Changes",
|
||||||
"command.viewStagedChanges": "View Staged Changes",
|
"command.viewStagedChanges": "View Staged Changes",
|
||||||
|
"command.openCommit": "Open Commit",
|
||||||
"command.api.getRepositories": "Get Repositories",
|
"command.api.getRepositories": "Get Repositories",
|
||||||
"command.api.getRepositoryState": "Get Repository State",
|
"command.api.getRepositoryState": "Get Repository State",
|
||||||
"command.api.getRemoteSources": "Get Remote Sources",
|
"command.api.getRemoteSources": "Get Remote Sources",
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { Command, commands, Disposable, LineChange, MessageOptions, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider, InputBoxValidationSeverity, TabInputText, TabInputTextMerge, QuickPickItemKind, TextDocument, LogOutputChannel, l10n, Memento, UIKind, QuickInputButton, ThemeIcon } from 'vscode';
|
import { Command, commands, Disposable, LineChange, MessageOptions, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider, InputBoxValidationSeverity, TabInputText, TabInputTextMerge, QuickPickItemKind, TextDocument, LogOutputChannel, l10n, Memento, UIKind, QuickInputButton, ThemeIcon, SourceControlHistoryItem } from 'vscode';
|
||||||
import TelemetryReporter from '@vscode/extension-telemetry';
|
import TelemetryReporter from '@vscode/extension-telemetry';
|
||||||
import { uniqueNamesGenerator, adjectives, animals, colors, NumberDictionary } from '@joaomoreno/unique-names-generator';
|
import { uniqueNamesGenerator, adjectives, animals, colors, NumberDictionary } from '@joaomoreno/unique-names-generator';
|
||||||
import { ForcePushMode, GitErrorCodes, Ref, RefType, Status, CommitOptions, RemoteSourcePublisher, Remote } from './api/git';
|
import { ForcePushMode, GitErrorCodes, Ref, RefType, Status, CommitOptions, RemoteSourcePublisher, Remote } from './api/git';
|
||||||
|
@ -3617,7 +3617,6 @@ export class CommandCenter {
|
||||||
|
|
||||||
@command('git.timeline.openCommit', { repository: false })
|
@command('git.timeline.openCommit', { repository: false })
|
||||||
async timelineOpenCommit(item: TimelineItem, uri: Uri | undefined, _source: string) {
|
async timelineOpenCommit(item: TimelineItem, uri: Uri | undefined, _source: string) {
|
||||||
console.log('timelineOpenCommit', item);
|
|
||||||
if (!GitTimelineItem.is(item)) {
|
if (!GitTimelineItem.is(item)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3840,6 +3839,29 @@ export class CommandCenter {
|
||||||
commands.executeCommand('vscode.changes', title, args);
|
commands.executeCommand('vscode.changes', title, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@command('git.openCommit', { repository: true })
|
||||||
|
async openCommit(repository: Repository, historyItem: SourceControlHistoryItem): Promise<void> {
|
||||||
|
if (!repository || !historyItem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const historyProvider = repository.historyProvider;
|
||||||
|
const historyItemParentId = historyItem.parentIds.length > 0 ? historyItem.parentIds[0] : undefined;
|
||||||
|
const historyItemChanges = await historyProvider.provideHistoryItemChanges(historyItem.id, historyItemParentId);
|
||||||
|
|
||||||
|
if (historyItemChanges.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modifiedShortRef = historyItem.id.substring(0, 8);
|
||||||
|
const originalShortRef = historyItem.parentIds.length > 0 ? historyItem.parentIds[0].substring(0, 8) : `${modifiedShortRef}^`;
|
||||||
|
|
||||||
|
const title = l10n.t('Changes ({0} ↔ {1})', originalShortRef, modifiedShortRef);
|
||||||
|
const args = historyItemChanges.map(change => [change.uri, change.originalUri, change.modifiedUri]);
|
||||||
|
|
||||||
|
commands.executeCommand('vscode.changes', title, args);
|
||||||
|
}
|
||||||
|
|
||||||
private createCommand(id: string, key: string, method: Function, options: ScmCommandOptions): (...args: any[]) => any {
|
private createCommand(id: string, key: string, method: Function, options: ScmCommandOptions): (...args: any[]) => any {
|
||||||
const result = (...args: any[]) => {
|
const result = (...args: any[]) => {
|
||||||
let result: Promise<any>;
|
let result: Promise<any>;
|
||||||
|
|
|
@ -796,6 +796,9 @@ export class Repository implements Disposable {
|
||||||
return this.repository.dotGit;
|
return this.repository.dotGit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _historyProvider: GitHistoryProvider;
|
||||||
|
get historyProvider(): GitHistoryProvider { return this._historyProvider; }
|
||||||
|
|
||||||
private isRepositoryHuge: false | { limit: number } = false;
|
private isRepositoryHuge: false | { limit: number } = false;
|
||||||
private didWarnAboutLimit = false;
|
private didWarnAboutLimit = false;
|
||||||
|
|
||||||
|
@ -850,9 +853,9 @@ export class Repository implements Disposable {
|
||||||
|
|
||||||
this._sourceControl.quickDiffProvider = this;
|
this._sourceControl.quickDiffProvider = this;
|
||||||
|
|
||||||
const historyProvider = new GitHistoryProvider(this, logger);
|
this._historyProvider = new GitHistoryProvider(this, logger);
|
||||||
this._sourceControl.historyProvider = historyProvider;
|
this._sourceControl.historyProvider = this._historyProvider;
|
||||||
this.disposables.push(historyProvider);
|
this.disposables.push(this._historyProvider);
|
||||||
|
|
||||||
this._sourceControl.acceptInputCommand = { command: 'git.commit', title: l10n.t('Commit'), arguments: [this._sourceControl] };
|
this._sourceControl.acceptInputCommand = { command: 'git.commit', title: l10n.t('Commit'), arguments: [this._sourceControl] };
|
||||||
this._sourceControl.inputBox.validateInput = this.validateInput.bind(this);
|
this._sourceControl.inputBox.validateInput = this.validateInput.bind(this);
|
||||||
|
|
|
@ -107,7 +107,8 @@ export class MenuId {
|
||||||
static readonly OpenEditorsContextShare = new MenuId('OpenEditorsContextShare');
|
static readonly OpenEditorsContextShare = new MenuId('OpenEditorsContextShare');
|
||||||
static readonly ProblemsPanelContext = new MenuId('ProblemsPanelContext');
|
static readonly ProblemsPanelContext = new MenuId('ProblemsPanelContext');
|
||||||
static readonly SCMInputBox = new MenuId('SCMInputBox');
|
static readonly SCMInputBox = new MenuId('SCMInputBox');
|
||||||
static readonly SCMHistoryItem = new MenuId('SCMHistoryItem');
|
static readonly SCMIncomingHistoryItemContext = new MenuId('SCMIncomingHistoryItemContext');
|
||||||
|
static readonly SCMOutgoingHistoryItemContext = new MenuId('SCMOutgoingHistoryItemContext');
|
||||||
static readonly SCMChangeContext = new MenuId('SCMChangeContext');
|
static readonly SCMChangeContext = new MenuId('SCMChangeContext');
|
||||||
static readonly SCMResourceContext = new MenuId('SCMResourceContext');
|
static readonly SCMResourceContext = new MenuId('SCMResourceContext');
|
||||||
static readonly SCMResourceContextShare = new MenuId('SCMResourceContextShare');
|
static readonly SCMResourceContextShare = new MenuId('SCMResourceContextShare');
|
||||||
|
|
|
@ -158,6 +158,7 @@ class MainThreadSCMHistoryProvider implements ISCMHistoryProvider {
|
||||||
id: historyItemGroupBase.id,
|
id: historyItemGroupBase.id,
|
||||||
label: historyItemGroupBase.label,
|
label: historyItemGroupBase.label,
|
||||||
icon: Codicon.arrowCircleDown,
|
icon: Codicon.arrowCircleDown,
|
||||||
|
direction: 'incoming',
|
||||||
ancestor: ancestor.id,
|
ancestor: ancestor.id,
|
||||||
count: ancestor.behind,
|
count: ancestor.behind,
|
||||||
};
|
};
|
||||||
|
@ -167,6 +168,7 @@ class MainThreadSCMHistoryProvider implements ISCMHistoryProvider {
|
||||||
id: historyItemGroup.id,
|
id: historyItemGroup.id,
|
||||||
label: historyItemGroup.label,
|
label: historyItemGroup.label,
|
||||||
icon: Codicon.arrowCircleUp,
|
icon: Codicon.arrowCircleUp,
|
||||||
|
direction: 'outgoing',
|
||||||
ancestor: ancestor.id,
|
ancestor: ancestor.id,
|
||||||
count: ancestor.ahead,
|
count: ancestor.ahead,
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { equals } from 'vs/base/common/arrays';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
import { ISCMHistoryItem, ISCMHistoryProviderMenus } from 'vs/workbench/contrib/scm/common/history';
|
import { ISCMHistoryItem, ISCMHistoryItemGroupEntry, ISCMHistoryProviderMenus } from 'vs/workbench/contrib/scm/common/history';
|
||||||
|
|
||||||
function actionEquals(a: IAction, b: IAction): boolean {
|
function actionEquals(a: IAction, b: IAction): boolean {
|
||||||
return a.id === b.id;
|
return a.id === b.id;
|
||||||
|
@ -177,7 +177,7 @@ export class SCMRepositoryMenus implements ISCMRepositoryMenus, IDisposable {
|
||||||
private _historyProviderMenu: SCMHistoryProviderMenus | undefined;
|
private _historyProviderMenu: SCMHistoryProviderMenus | undefined;
|
||||||
get historyProviderMenu(): SCMHistoryProviderMenus | undefined {
|
get historyProviderMenu(): SCMHistoryProviderMenus | undefined {
|
||||||
if (this.provider.historyProvider && !this._historyProviderMenu) {
|
if (this.provider.historyProvider && !this._historyProviderMenu) {
|
||||||
this._historyProviderMenu = this.instantiationService.createInstance(SCMHistoryProviderMenus);
|
this._historyProviderMenu = new SCMHistoryProviderMenus(this.contextKeyService, this.menuService);
|
||||||
this.disposables.add(this._historyProviderMenu);
|
this.disposables.add(this._historyProviderMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ export class SCMRepositoryMenus implements ISCMRepositoryMenus, IDisposable {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly provider: ISCMProvider,
|
private readonly provider: ISCMProvider,
|
||||||
@IContextKeyService contextKeyService: IContextKeyService,
|
@IContextKeyService contextKeyService: IContextKeyService,
|
||||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
@IInstantiationService instantiationService: IInstantiationService,
|
||||||
@IMenuService private readonly menuService: IMenuService
|
@IMenuService private readonly menuService: IMenuService
|
||||||
) {
|
) {
|
||||||
this.contextKeyService = contextKeyService.createOverlay([
|
this.contextKeyService = contextKeyService.createOverlay([
|
||||||
|
@ -261,11 +261,11 @@ export class SCMHistoryProviderMenus implements ISCMHistoryProviderMenus, IDispo
|
||||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||||
@IMenuService private readonly menuService: IMenuService) { }
|
@IMenuService private readonly menuService: IMenuService) { }
|
||||||
|
|
||||||
getHistoryItemMenu(historyItem: ISCMHistoryItem): IMenu {
|
getHistoryItemMenu(historyItemGroup: ISCMHistoryItemGroupEntry, historyItem: ISCMHistoryItem): IMenu {
|
||||||
return this.getOrCreateHistoryItemMenu(historyItem);
|
return this.getOrCreateHistoryItemMenu(historyItemGroup, historyItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getOrCreateHistoryItemMenu(historyItem: ISCMHistoryItem): IMenu {
|
private getOrCreateHistoryItemMenu(historyItemGroup: ISCMHistoryItemGroupEntry, historyItem: ISCMHistoryItem): IMenu {
|
||||||
let result = this.historyItemMenus.get(historyItem);
|
let result = this.historyItemMenus.get(historyItem);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
@ -273,7 +273,10 @@ export class SCMHistoryProviderMenus implements ISCMHistoryProviderMenus, IDispo
|
||||||
['scmHistoryItem', historyItem.id],
|
['scmHistoryItem', historyItem.id],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
result = this.menuService.createMenu(MenuId.SCMHistoryItem, contextKeyService);
|
const menuId = historyItemGroup.direction === 'incoming' ?
|
||||||
|
MenuId.SCMIncomingHistoryItemContext : MenuId.SCMOutgoingHistoryItemContext;
|
||||||
|
|
||||||
|
result = this.menuService.createMenu(menuId, contextKeyService);
|
||||||
this.historyItemMenus.set(historyItem, result);
|
this.historyItemMenus.set(historyItem, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { ViewPane, IViewPaneOptions, ViewAction } from 'vs/workbench/browser/par
|
||||||
import { append, $, Dimension, asCSSUrl, trackFocus, clearNode, prepend } from 'vs/base/browser/dom';
|
import { append, $, Dimension, asCSSUrl, trackFocus, clearNode, prepend } from 'vs/base/browser/dom';
|
||||||
import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list';
|
import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list';
|
||||||
import { ISCMHistoryItem, ISCMHistoryItemChange, ISCMHistoryProviderCacheEntry, SCMHistoryItemChangeTreeElement, SCMHistoryItemGroupTreeElement, SCMHistoryItemTreeElement, SCMViewSeparatorElement } from 'vs/workbench/contrib/scm/common/history';
|
import { ISCMHistoryItem, ISCMHistoryItemChange, ISCMHistoryProviderCacheEntry, SCMHistoryItemChangeTreeElement, SCMHistoryItemGroupTreeElement, SCMHistoryItemTreeElement, SCMViewSeparatorElement } from 'vs/workbench/contrib/scm/common/history';
|
||||||
import { ISCMResourceGroup, ISCMResource, InputValidationType, ISCMRepository, ISCMInput, IInputValidation, ISCMViewService, ISCMViewVisibleRepositoryChangeEvent, ISCMService, SCMInputChangeReason, VIEW_PANE_ID, ISCMActionButton, ISCMActionButtonDescriptor, ISCMRepositorySortKey, REPOSITORIES_VIEW_PANE_ID, ISCMInputValueProviderContext } from 'vs/workbench/contrib/scm/common/scm';
|
import { ISCMResourceGroup, ISCMResource, InputValidationType, ISCMRepository, ISCMInput, IInputValidation, ISCMViewService, ISCMViewVisibleRepositoryChangeEvent, ISCMService, SCMInputChangeReason, VIEW_PANE_ID, ISCMActionButton, ISCMActionButtonDescriptor, ISCMRepositorySortKey, REPOSITORIES_VIEW_PANE_ID, ISCMInputValueProviderContext, ISCMProvider } from 'vs/workbench/contrib/scm/common/scm';
|
||||||
import { ResourceLabels, IResourceLabel, IFileLabelOptions } from 'vs/workbench/browser/labels';
|
import { ResourceLabels, IResourceLabel, IFileLabelOptions } from 'vs/workbench/browser/labels';
|
||||||
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
|
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
|
||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
|
@ -21,7 +21,7 @@ import { IContextKeyService, IContextKey, ContextKeyExpr, RawContextKey } from '
|
||||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||||
import { MenuItemAction, IMenuService, registerAction2, MenuId, IAction2Options, MenuRegistry, Action2, IMenu } from 'vs/platform/actions/common/actions';
|
import { MenuItemAction, IMenuService, registerAction2, MenuId, IAction2Options, MenuRegistry, Action2, IMenu } from 'vs/platform/actions/common/actions';
|
||||||
import { IAction, ActionRunner, Action, Separator } from 'vs/base/common/actions';
|
import { IAction, ActionRunner, Action, Separator, IActionRunner } from 'vs/base/common/actions';
|
||||||
import { ActionBar, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { ActionBar, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
import { IThemeService, IFileIconTheme } from 'vs/platform/theme/common/themeService';
|
import { IThemeService, IFileIconTheme } from 'vs/platform/theme/common/themeService';
|
||||||
import { isSCMResource, isSCMResourceGroup, connectPrimaryMenuToInlineActionBar, isSCMRepository, isSCMInput, collectContextMenuActions, getActionViewItemProvider, isSCMActionButton, isSCMViewService, isSCMHistoryItemGroupTreeElement, isSCMHistoryItemTreeElement, isSCMHistoryItemChangeTreeElement, toDiffEditorArguments, isSCMResourceNode, isSCMHistoryItemChangeNode, isSCMViewSeparator } from './util';
|
import { isSCMResource, isSCMResourceGroup, connectPrimaryMenuToInlineActionBar, isSCMRepository, isSCMInput, collectContextMenuActions, getActionViewItemProvider, isSCMActionButton, isSCMViewService, isSCMHistoryItemGroupTreeElement, isSCMHistoryItemTreeElement, isSCMHistoryItemChangeTreeElement, toDiffEditorArguments, isSCMResourceNode, isSCMHistoryItemChangeNode, isSCMViewSeparator } from './util';
|
||||||
|
@ -808,6 +808,29 @@ class HistoryItemGroupRenderer implements ICompressibleTreeRenderer<SCMHistoryIt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HistoryItemActionRunner extends ActionRunner {
|
||||||
|
|
||||||
|
protected override async runAction(action: IAction, context: SCMHistoryItemTreeElement): Promise<any> {
|
||||||
|
if (!(action instanceof MenuItemAction)) {
|
||||||
|
return super.runAction(action, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
const args: (ISCMProvider | ISCMHistoryItem)[] = [];
|
||||||
|
args.push(context.historyItemGroup.repository.provider);
|
||||||
|
args.push({
|
||||||
|
id: context.id,
|
||||||
|
parentIds: context.parentIds,
|
||||||
|
label: context.label,
|
||||||
|
description: context.description,
|
||||||
|
icon: context.icon,
|
||||||
|
timestamp: context.timestamp,
|
||||||
|
statistics: context.statistics,
|
||||||
|
} satisfies ISCMHistoryItem);
|
||||||
|
|
||||||
|
await action.run(...args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface HistoryItemTemplate {
|
interface HistoryItemTemplate {
|
||||||
readonly iconContainer: HTMLElement;
|
readonly iconContainer: HTMLElement;
|
||||||
readonly label: IconLabel;
|
readonly label: IconLabel;
|
||||||
|
@ -826,6 +849,7 @@ class HistoryItemRenderer implements ICompressibleTreeRenderer<SCMHistoryItemTre
|
||||||
get templateId(): string { return HistoryItemRenderer.TEMPLATE_ID; }
|
get templateId(): string { return HistoryItemRenderer.TEMPLATE_ID; }
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private actionRunner: IActionRunner,
|
||||||
private actionViewItemProvider: IActionViewItemProvider,
|
private actionViewItemProvider: IActionViewItemProvider,
|
||||||
@ISCMViewService private scmViewService: ISCMViewService) { }
|
@ISCMViewService private scmViewService: ISCMViewService) { }
|
||||||
|
|
||||||
|
@ -840,7 +864,7 @@ class HistoryItemRenderer implements ICompressibleTreeRenderer<SCMHistoryItemTre
|
||||||
|
|
||||||
const disposables = new DisposableStore();
|
const disposables = new DisposableStore();
|
||||||
const actionsContainer = append(element, $('.actions'));
|
const actionsContainer = append(element, $('.actions'));
|
||||||
const actionBar = new ActionBar(actionsContainer, { actionViewItemProvider: this.actionViewItemProvider });
|
const actionBar = new ActionBar(actionsContainer, { actionRunner: this.actionRunner, actionViewItemProvider: this.actionViewItemProvider });
|
||||||
disposables.add(actionBar);
|
disposables.add(actionBar);
|
||||||
|
|
||||||
const statsContainer = append(element, $('.stats-container'));
|
const statsContainer = append(element, $('.stats-container'));
|
||||||
|
@ -866,7 +890,8 @@ class HistoryItemRenderer implements ICompressibleTreeRenderer<SCMHistoryItemTre
|
||||||
|
|
||||||
const menus = this.scmViewService.menus.getRepositoryMenus(historyItem.historyItemGroup.repository.provider);
|
const menus = this.scmViewService.menus.getRepositoryMenus(historyItem.historyItemGroup.repository.provider);
|
||||||
if (menus.historyProviderMenu) {
|
if (menus.historyProviderMenu) {
|
||||||
templateData.elementDisposables.add(connectPrimaryMenuToInlineActionBar(menus.historyProviderMenu.getHistoryItemMenu(historyItem), templateData.actionBar));
|
const historyItemMenu = menus.historyProviderMenu.getHistoryItemMenu(historyItem.historyItemGroup, historyItem);
|
||||||
|
templateData.elementDisposables.add(connectPrimaryMenuToInlineActionBar(historyItemMenu, templateData.actionBar));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.renderStatistics(node, index, templateData, height);
|
this.renderStatistics(node, index, templateData, height);
|
||||||
|
@ -1698,53 +1723,6 @@ class ExpandAllRepositoriesAction extends ViewAction<SCMViewPane> {
|
||||||
registerAction2(CollapseAllRepositoriesAction);
|
registerAction2(CollapseAllRepositoriesAction);
|
||||||
registerAction2(ExpandAllRepositoriesAction);
|
registerAction2(ExpandAllRepositoriesAction);
|
||||||
|
|
||||||
class HistoryItemViewChangesAction extends Action2 {
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super({
|
|
||||||
id: `workbench.scm.action.historyItemViewChanges`,
|
|
||||||
title: localize('historyItemViewChanges', "View Changes"),
|
|
||||||
icon: Codicon.diffMultiple,
|
|
||||||
f1: false,
|
|
||||||
menu: {
|
|
||||||
id: MenuId.SCMHistoryItem,
|
|
||||||
group: 'inline',
|
|
||||||
when: ContextKeyExpr.has('config.multiDiffEditor.experimental.enabled'),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(accessor: ServicesAccessor, historyItem: SCMHistoryItemTreeElement): Promise<void> {
|
|
||||||
const commandService = accessor.get(ICommandService);
|
|
||||||
|
|
||||||
const historyProvider = historyItem.historyItemGroup.repository.provider.historyProvider;
|
|
||||||
if (!historyProvider) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const historyItemParentId = historyItem.parentIds.length > 0 ? historyItem.parentIds[0] : undefined;
|
|
||||||
const historyItemChanges = await historyProvider.provideHistoryItemChanges(historyItem.id, historyItemParentId);
|
|
||||||
if (!historyItemChanges || historyItemChanges.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let [originalRef, modifiedRef] = historyItem.id.includes('..')
|
|
||||||
? historyItem.id.split('..').map(id => id.substring(0, 8)) : [undefined, historyItem.id.substring(0, 8)];
|
|
||||||
|
|
||||||
if (!originalRef) {
|
|
||||||
originalRef = historyItem.parentIds.length > 0 ? historyItem.parentIds[0].substring(0, 8) : `${modifiedRef}^`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const title = localize('historyItemChangesTitle', "Changes ({0} ↔ {1})", originalRef, modifiedRef);
|
|
||||||
const args = historyItemChanges.map(change => [change.uri, change.originalUri, change.modifiedUri]);
|
|
||||||
|
|
||||||
return commandService.executeCommand('_workbench.changes', title, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
registerAction2(HistoryItemViewChangesAction);
|
|
||||||
|
|
||||||
const enum SCMInputWidgetCommandId {
|
const enum SCMInputWidgetCommandId {
|
||||||
CancelAction = 'scm.input.cancelAction'
|
CancelAction = 'scm.input.cancelAction'
|
||||||
}
|
}
|
||||||
|
@ -2742,9 +2720,13 @@ export class SCMViewPane extends ViewPane {
|
||||||
this.listLabels = this.instantiationService.createInstance(ResourceLabels, { onDidChangeVisibility: this.onDidChangeBodyVisibility });
|
this.listLabels = this.instantiationService.createInstance(ResourceLabels, { onDidChangeVisibility: this.onDidChangeBodyVisibility });
|
||||||
this.disposables.add(this.listLabels);
|
this.disposables.add(this.listLabels);
|
||||||
|
|
||||||
const actionRunner = new RepositoryPaneActionRunner(() => this.getSelectedResources());
|
const resourceActionRunner = new RepositoryPaneActionRunner(() => this.getSelectedResources());
|
||||||
actionRunner.onWillRun(() => this.tree.domFocus(), this, this.disposables);
|
resourceActionRunner.onWillRun(() => this.tree.domFocus(), this, this.disposables);
|
||||||
this.disposables.add(actionRunner);
|
this.disposables.add(resourceActionRunner);
|
||||||
|
|
||||||
|
const historyItemActionRunner = new HistoryItemActionRunner();
|
||||||
|
historyItemActionRunner.onWillRun(() => this.tree.domFocus(), this, this.disposables);
|
||||||
|
this.disposables.add(historyItemActionRunner);
|
||||||
|
|
||||||
const treeDataSource = this.instantiationService.createInstance(SCMTreeDataSource, () => this.viewMode, () => this.alwaysShowRepositories, () => this.showActionButton, () => this.showIncomingChanges, () => this.showOutgoingChanges);
|
const treeDataSource = this.instantiationService.createInstance(SCMTreeDataSource, () => this.viewMode, () => this.alwaysShowRepositories, () => this.showActionButton, () => this.showIncomingChanges, () => this.showOutgoingChanges);
|
||||||
this.disposables.add(treeDataSource);
|
this.disposables.add(treeDataSource);
|
||||||
|
@ -2760,9 +2742,9 @@ export class SCMViewPane extends ViewPane {
|
||||||
this.actionButtonRenderer,
|
this.actionButtonRenderer,
|
||||||
this.instantiationService.createInstance(RepositoryRenderer, MenuId.SCMTitle, getActionViewItemProvider(this.instantiationService)),
|
this.instantiationService.createInstance(RepositoryRenderer, MenuId.SCMTitle, getActionViewItemProvider(this.instantiationService)),
|
||||||
this.instantiationService.createInstance(ResourceGroupRenderer, getActionViewItemProvider(this.instantiationService)),
|
this.instantiationService.createInstance(ResourceGroupRenderer, getActionViewItemProvider(this.instantiationService)),
|
||||||
this.instantiationService.createInstance(ResourceRenderer, () => this.viewMode, this.listLabels, getActionViewItemProvider(this.instantiationService), actionRunner),
|
this.instantiationService.createInstance(ResourceRenderer, () => this.viewMode, this.listLabels, getActionViewItemProvider(this.instantiationService), resourceActionRunner),
|
||||||
this.instantiationService.createInstance(HistoryItemGroupRenderer),
|
this.instantiationService.createInstance(HistoryItemGroupRenderer),
|
||||||
this.instantiationService.createInstance(HistoryItemRenderer, getActionViewItemProvider(this.instantiationService)),
|
this.instantiationService.createInstance(HistoryItemRenderer, historyItemActionRunner, getActionViewItemProvider(this.instantiationService)),
|
||||||
this.instantiationService.createInstance(HistoryItemChangeRenderer, () => this.viewMode, this.listLabels),
|
this.instantiationService.createInstance(HistoryItemChangeRenderer, () => this.viewMode, this.listLabels),
|
||||||
this.instantiationService.createInstance(SeparatorRenderer)
|
this.instantiationService.createInstance(SeparatorRenderer)
|
||||||
],
|
],
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { IMenu } from 'vs/platform/actions/common/actions';
|
||||||
import { ISCMRepository } from 'vs/workbench/contrib/scm/common/scm';
|
import { ISCMRepository } from 'vs/workbench/contrib/scm/common/scm';
|
||||||
|
|
||||||
export interface ISCMHistoryProviderMenus {
|
export interface ISCMHistoryProviderMenus {
|
||||||
getHistoryItemMenu(historyItem: ISCMHistoryItem): IMenu;
|
getHistoryItemMenu(historyItemGroup: ISCMHistoryItemGroupEntry, historyItem: ISCMHistoryItem): IMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISCMHistoryProvider {
|
export interface ISCMHistoryProvider {
|
||||||
|
@ -57,6 +57,7 @@ export interface ISCMHistoryItemGroupDetails {
|
||||||
export interface ISCMHistoryItemGroupEntry {
|
export interface ISCMHistoryItemGroupEntry {
|
||||||
readonly id: string;
|
readonly id: string;
|
||||||
readonly label: string;
|
readonly label: string;
|
||||||
|
readonly direction: 'incoming' | 'outgoing';
|
||||||
readonly icon?: URI | { light: URI; dark: URI } | ThemeIcon;
|
readonly icon?: URI | { light: URI; dark: URI } | ThemeIcon;
|
||||||
readonly description?: string;
|
readonly description?: string;
|
||||||
readonly ancestor?: string;
|
readonly ancestor?: string;
|
||||||
|
|
|
@ -150,6 +150,18 @@ const apiMenus: IAPIMenu[] = [
|
||||||
description: localize('menus.input', "The Source Control input box menu"),
|
description: localize('menus.input', "The Source Control input box menu"),
|
||||||
proposed: 'contribSourceControlInputBoxMenu'
|
proposed: 'contribSourceControlInputBoxMenu'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'scm/incoming/historyItem/context',
|
||||||
|
id: MenuId.SCMIncomingHistoryItemContext,
|
||||||
|
description: localize('menus.incomingHistoryItemContext', "The Source Control incoming history item context menu"),
|
||||||
|
proposed: 'contribSourceControlHistoryItemMenu'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'scm/outgoing/historyItem/context',
|
||||||
|
id: MenuId.SCMOutgoingHistoryItemContext,
|
||||||
|
description: localize('menus.outgoingHistoryItemContext', "The Source Control outgoing history item context menu"),
|
||||||
|
proposed: 'contribSourceControlHistoryItemMenu'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'statusBar/remoteIndicator',
|
key: 'statusBar/remoteIndicator',
|
||||||
id: MenuId.StatusBarRemoteIndicatorMenu,
|
id: MenuId.StatusBarRemoteIndicatorMenu,
|
||||||
|
|
|
@ -32,6 +32,7 @@ export const allApiProposals = Object.freeze({
|
||||||
contribNotebookStaticPreloads: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribNotebookStaticPreloads.d.ts',
|
contribNotebookStaticPreloads: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribNotebookStaticPreloads.d.ts',
|
||||||
contribRemoteHelp: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribRemoteHelp.d.ts',
|
contribRemoteHelp: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribRemoteHelp.d.ts',
|
||||||
contribShareMenu: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribShareMenu.d.ts',
|
contribShareMenu: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribShareMenu.d.ts',
|
||||||
|
contribSourceControlHistoryItemMenu: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribSourceControlHistoryItemMenu.d.ts',
|
||||||
contribSourceControlInputBoxMenu: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribSourceControlInputBoxMenu.d.ts',
|
contribSourceControlInputBoxMenu: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribSourceControlInputBoxMenu.d.ts',
|
||||||
contribStatusBarItems: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribStatusBarItems.d.ts',
|
contribStatusBarItems: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribStatusBarItems.d.ts',
|
||||||
contribViewsRemote: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribViewsRemote.d.ts',
|
contribViewsRemote: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribViewsRemote.d.ts',
|
||||||
|
|
7
src/vscode-dts/vscode.proposed.contribSourceControlHistoryItemMenu.d.ts
vendored
Normal file
7
src/vscode-dts/vscode.proposed.contribSourceControlHistoryItemMenu.d.ts
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// empty placeholder declaration for the `scm/historyItem/context`-menu contribution point
|
||||||
|
// https://github.com/microsoft/vscode/issues/201997
|
Loading…
Reference in a new issue