mirror of
https://github.com/Microsoft/vscode
synced 2024-08-28 05:19:39 +00:00
Fixes #110496 - use builtin gestures for open/diff
This commit is contained in:
parent
392128e1fe
commit
4fc8dc82f3
|
@ -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 { commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider } from 'vscode';
|
import { Command, commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider } from 'vscode';
|
||||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
import { Branch, ForcePushMode, GitErrorCodes, Ref, RefType, Status, CommitOptions, RemoteSourceProvider } from './api/git';
|
import { Branch, ForcePushMode, GitErrorCodes, Ref, RefType, Status, CommitOptions, RemoteSourceProvider } from './api/git';
|
||||||
|
@ -153,21 +153,21 @@ class AddRemoteItem implements QuickPickItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CommandOptions {
|
interface ScmCommandOptions {
|
||||||
repository?: boolean;
|
repository?: boolean;
|
||||||
diff?: boolean;
|
diff?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Command {
|
interface ScmCommand {
|
||||||
commandId: string;
|
commandId: string;
|
||||||
key: string;
|
key: string;
|
||||||
method: Function;
|
method: Function;
|
||||||
options: CommandOptions;
|
options: ScmCommandOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Commands: Command[] = [];
|
const Commands: ScmCommand[] = [];
|
||||||
|
|
||||||
function command(commandId: string, options: CommandOptions = {}): Function {
|
function command(commandId: string, options: ScmCommandOptions = {}): Function {
|
||||||
return (_target: any, key: string, descriptor: any) => {
|
return (_target: any, key: string, descriptor: any) => {
|
||||||
if (!(typeof descriptor.value === 'function')) {
|
if (!(typeof descriptor.value === 'function')) {
|
||||||
throw new Error('not supported');
|
throw new Error('not supported');
|
||||||
|
@ -2612,6 +2612,22 @@ export class CommandCenter {
|
||||||
|
|
||||||
@command('git.timeline.openDiff', { repository: false })
|
@command('git.timeline.openDiff', { repository: false })
|
||||||
async timelineOpenDiff(item: TimelineItem, uri: Uri | undefined, _source: string) {
|
async timelineOpenDiff(item: TimelineItem, uri: Uri | undefined, _source: string) {
|
||||||
|
const cmd = this.resolveTimelineOpenDiffCommand(
|
||||||
|
item, uri,
|
||||||
|
{
|
||||||
|
preserveFocus: true,
|
||||||
|
preview: true,
|
||||||
|
viewColumn: ViewColumn.Active
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (cmd === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return commands.executeCommand(cmd.command, ...(cmd.arguments ?? []));
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveTimelineOpenDiffCommand(item: TimelineItem, uri: Uri | undefined, options?: TextDocumentShowOptions): Command | undefined {
|
||||||
if (uri === undefined || uri === null || !GitTimelineItem.is(item)) {
|
if (uri === undefined || uri === null || !GitTimelineItem.is(item)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -2628,13 +2644,11 @@ export class CommandCenter {
|
||||||
title = localize('git.title.diffRefs', '{0} ({1}) ⟷ {0} ({2})', basename, item.shortPreviousRef, item.shortRef);
|
title = localize('git.title.diffRefs', '{0} ({1}) ⟷ {0} ({2})', basename, item.shortPreviousRef, item.shortRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
const options: TextDocumentShowOptions = {
|
return {
|
||||||
preserveFocus: true,
|
command: 'vscode.diff',
|
||||||
preview: true,
|
title: 'Open Comparison',
|
||||||
viewColumn: ViewColumn.Active
|
arguments: [toGitUri(uri, item.previousRef), item.ref === '' ? uri : toGitUri(uri, item.ref), title, options]
|
||||||
};
|
};
|
||||||
|
|
||||||
return commands.executeCommand('vscode.diff', toGitUri(uri, item.previousRef), item.ref === '' ? uri : toGitUri(uri, item.ref), title, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@command('git.timeline.copyCommitId', { repository: false })
|
@command('git.timeline.copyCommitId', { repository: false })
|
||||||
|
@ -2664,7 +2678,7 @@ export class CommandCenter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private createCommand(id: string, key: string, method: Function, options: CommandOptions): (...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>;
|
||||||
|
|
||||||
|
|
|
@ -73,12 +73,13 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
|
||||||
git.onOutput.addListener('log', onOutput);
|
git.onOutput.addListener('log', onOutput);
|
||||||
disposables.push(toDisposable(() => git.onOutput.removeListener('log', onOutput)));
|
disposables.push(toDisposable(() => git.onOutput.removeListener('log', onOutput)));
|
||||||
|
|
||||||
|
const cc = new CommandCenter(git, model, outputChannel, telemetryReporter);
|
||||||
disposables.push(
|
disposables.push(
|
||||||
new CommandCenter(git, model, outputChannel, telemetryReporter),
|
cc,
|
||||||
new GitFileSystemProvider(model),
|
new GitFileSystemProvider(model),
|
||||||
new GitDecorations(model),
|
new GitDecorations(model),
|
||||||
new GitProtocolHandler(),
|
new GitProtocolHandler(),
|
||||||
new GitTimelineProvider(model)
|
new GitTimelineProvider(model, cc)
|
||||||
);
|
);
|
||||||
|
|
||||||
checkGitVersion(info);
|
checkGitVersion(info);
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { Model } from './model';
|
||||||
import { Repository, Resource } from './repository';
|
import { Repository, Resource } from './repository';
|
||||||
import { debounce } from './decorators';
|
import { debounce } from './decorators';
|
||||||
import { emojify, ensureEmojis } from './emoji';
|
import { emojify, ensureEmojis } from './emoji';
|
||||||
|
import { CommandCenter } from './commands';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||||
private repoDisposable: Disposable | undefined;
|
private repoDisposable: Disposable | undefined;
|
||||||
private repoStatusDate: Date | undefined;
|
private repoStatusDate: Date | undefined;
|
||||||
|
|
||||||
constructor(private readonly model: Model) {
|
constructor(private readonly model: Model, private commands: CommandCenter) {
|
||||||
this.disposable = Disposable.from(
|
this.disposable = Disposable.from(
|
||||||
model.onDidOpenRepository(this.onRepositoriesChanged, this),
|
model.onDidOpenRepository(this.onRepositoriesChanged, this),
|
||||||
workspace.onDidChangeConfiguration(this.onConfigurationChanged, this)
|
workspace.onDidChangeConfiguration(this.onConfigurationChanged, this)
|
||||||
|
@ -161,16 +162,20 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||||
const message = emojify(c.message);
|
const message = emojify(c.message);
|
||||||
|
|
||||||
const item = new GitTimelineItem(c.hash, commits[i + 1]?.hash ?? `${c.hash}^`, message, date?.getTime() ?? 0, c.hash, 'git:file:commit');
|
const item = new GitTimelineItem(c.hash, commits[i + 1]?.hash ?? `${c.hash}^`, message, date?.getTime() ?? 0, c.hash, 'git:file:commit');
|
||||||
item.iconPath = new (ThemeIcon as any)('git-commit');
|
item.iconPath = new ThemeIcon('git-commit');
|
||||||
if (showAuthor) {
|
if (showAuthor) {
|
||||||
item.description = c.authorName;
|
item.description = c.authorName;
|
||||||
}
|
}
|
||||||
item.detail = `${c.authorName} (${c.authorEmail}) — ${c.hash.substr(0, 8)}\n${dateFormatter.format(date)}\n\n${message}`;
|
item.detail = `${c.authorName} (${c.authorEmail}) — ${c.hash.substr(0, 8)}\n${dateFormatter.format(date)}\n\n${message}`;
|
||||||
item.command = {
|
|
||||||
title: 'Open Comparison',
|
const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri);
|
||||||
command: 'git.timeline.openDiff',
|
if (cmd) {
|
||||||
arguments: [item, uri, this.id]
|
item.command = {
|
||||||
};
|
title: 'Open Comparison',
|
||||||
|
command: cmd.command,
|
||||||
|
arguments: cmd.arguments,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
|
@ -184,14 +189,18 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||||
|
|
||||||
const item = new GitTimelineItem('~', 'HEAD', localize('git.timeline.stagedChanges', 'Staged Changes'), date.getTime(), 'index', 'git:file:index');
|
const item = new GitTimelineItem('~', 'HEAD', localize('git.timeline.stagedChanges', 'Staged Changes'), date.getTime(), 'index', 'git:file:index');
|
||||||
// TODO@eamodio: Replace with a better icon -- reflecting its status maybe?
|
// TODO@eamodio: Replace with a better icon -- reflecting its status maybe?
|
||||||
item.iconPath = new (ThemeIcon as any)('git-commit');
|
item.iconPath = new ThemeIcon('git-commit');
|
||||||
item.description = '';
|
item.description = '';
|
||||||
item.detail = localize('git.timeline.detail', '{0} — {1}\n{2}\n\n{3}', you, localize('git.index', 'Index'), dateFormatter.format(date), Resource.getStatusText(index.type));
|
item.detail = localize('git.timeline.detail', '{0} — {1}\n{2}\n\n{3}', you, localize('git.index', 'Index'), dateFormatter.format(date), Resource.getStatusText(index.type));
|
||||||
item.command = {
|
|
||||||
title: 'Open Comparison',
|
const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri);
|
||||||
command: 'git.timeline.openDiff',
|
if (cmd) {
|
||||||
arguments: [item, uri, this.id]
|
item.command = {
|
||||||
};
|
title: 'Open Comparison',
|
||||||
|
command: cmd.command,
|
||||||
|
arguments: cmd.arguments,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
items.splice(0, 0, item);
|
items.splice(0, 0, item);
|
||||||
}
|
}
|
||||||
|
@ -202,14 +211,18 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||||
|
|
||||||
const item = new GitTimelineItem('', index ? '~' : 'HEAD', localize('git.timeline.uncommitedChanges', 'Uncommitted Changes'), date.getTime(), 'working', 'git:file:working');
|
const item = new GitTimelineItem('', index ? '~' : 'HEAD', localize('git.timeline.uncommitedChanges', 'Uncommitted Changes'), date.getTime(), 'working', 'git:file:working');
|
||||||
// TODO@eamodio: Replace with a better icon -- reflecting its status maybe?
|
// TODO@eamodio: Replace with a better icon -- reflecting its status maybe?
|
||||||
item.iconPath = new (ThemeIcon as any)('git-commit');
|
item.iconPath = new ThemeIcon('git-commit');
|
||||||
item.description = '';
|
item.description = '';
|
||||||
item.detail = localize('git.timeline.detail', '{0} — {1}\n{2}\n\n{3}', you, localize('git.workingTree', 'Working Tree'), dateFormatter.format(date), Resource.getStatusText(working.type));
|
item.detail = localize('git.timeline.detail', '{0} — {1}\n{2}\n\n{3}', you, localize('git.workingTree', 'Working Tree'), dateFormatter.format(date), Resource.getStatusText(working.type));
|
||||||
item.command = {
|
|
||||||
title: 'Open Comparison',
|
const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri);
|
||||||
command: 'git.timeline.openDiff',
|
if (cmd) {
|
||||||
arguments: [item, uri, this.id]
|
item.command = {
|
||||||
};
|
title: 'Open Comparison',
|
||||||
|
command: cmd.command,
|
||||||
|
arguments: cmd.arguments,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
items.splice(0, 0, item);
|
items.splice(0, 0, item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||||
import { ColorScheme } from 'vs/platform/theme/common/theme';
|
import { ColorScheme } from 'vs/platform/theme/common/theme';
|
||||||
import { Codicon } from 'vs/base/common/codicons';
|
import { Codicon } from 'vs/base/common/codicons';
|
||||||
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
|
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
|
||||||
|
import { API_OPEN_DIFF_EDITOR_COMMAND_ID, API_OPEN_EDITOR_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands';
|
||||||
|
|
||||||
const ItemHeight = 22;
|
const ItemHeight = 22;
|
||||||
|
|
||||||
|
@ -888,6 +889,7 @@ export class TimelinePane extends ViewPane {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
keyboardNavigationLabelProvider: new TimelineKeyboardNavigationLabelProvider(),
|
keyboardNavigationLabelProvider: new TimelineKeyboardNavigationLabelProvider(),
|
||||||
|
multipleSelectionSupport: true,
|
||||||
overrideStyles: {
|
overrideStyles: {
|
||||||
listBackground: this.getBackgroundColor(),
|
listBackground: this.getBackgroundColor(),
|
||||||
}
|
}
|
||||||
|
@ -900,14 +902,29 @@ export class TimelinePane extends ViewPane {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const item = e.element;
|
const selection = this.tree.getSelection();
|
||||||
|
let item;
|
||||||
|
if (selection.length === 1) {
|
||||||
|
item = selection[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// const item = e.element;
|
||||||
if (item === null) {
|
if (item === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTimelineItem(item)) {
|
if (isTimelineItem(item)) {
|
||||||
if (item.command) {
|
if (item.command) {
|
||||||
this.commandService.executeCommand(item.command.id, ...(item.command.arguments || []));
|
let args = item.command.arguments ?? [];
|
||||||
|
if (item.command.id === API_OPEN_EDITOR_COMMAND_ID || item.command.id === API_OPEN_DIFF_EDITOR_COMMAND_ID) {
|
||||||
|
// Some commands owned by us should receive the
|
||||||
|
// `IOpenEvent` as context to open properly
|
||||||
|
args = [...args, e];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.commandService.executeCommand(item.command.id, ...args);
|
||||||
|
|
||||||
|
// this.commandService.executeCommand(item.command.id, ...(item.command.arguments || []));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isLoadMoreCommand(item)) {
|
else if (isLoadMoreCommand(item)) {
|
||||||
|
|
Loading…
Reference in a new issue