Browse Source

Implements events for file and commit selection

- visual file history listens for files and sends commit selection
- commit details listens for commits
- rebase editor, commits, stashes and graph views send commit selection
main
Keith Daulton 1 year ago
parent
commit
d4a62ce398
6 changed files with 165 additions and 75 deletions
  1. +38
    -13
      src/plus/webviews/graph/graphWebview.ts
  2. +29
    -3
      src/plus/webviews/timeline/timelineWebviewView.ts
  3. +39
    -1
      src/views/commitsView.ts
  4. +34
    -1
      src/views/stashesView.ts
  5. +11
    -51
      src/webviews/commitDetails/commitDetailsWebviewView.ts
  6. +14
    -6
      src/webviews/rebase/rebaseEditor.ts

+ 38
- 13
src/plus/webviews/graph/graphWebview.ts View File

@ -480,11 +480,18 @@ export class GraphWebview extends WebviewBase {
const { activeSelection } = this;
if (activeSelection == null) return;
void GitActions.Commit.showDetailsView(activeSelection, {
pin: false,
preserveFocus: true,
preserveVisibility: this._showDetailsView === false,
});
this.container.events.fire(
'commit:selected',
{
commit: activeSelection,
pin: false,
preserveFocus: true,
preserveVisibility: this._showDetailsView === false,
},
{
source: this.id,
},
);
}
protected override onVisibilityChanged(visible: boolean): void {
@ -645,7 +652,18 @@ export class GraphWebview extends WebviewBase {
}
} else if (e.type === 'row' && e.row) {
const commit = this.getRevisionReference(this.repository?.path, e.row.id, e.row.type);
if (commit != null) return GitActions.Commit.showDetailsView(commit, { preserveFocus: e.preserveFocus });
if (commit != null) {
this.container.events.fire(
'commit:selected',
{
commit: commit,
preserveFocus: e.preserveFocus,
},
{
source: this.id,
},
);
}
}
return Promise.resolve();
@ -942,13 +960,20 @@ export class GraphWebview extends WebviewBase {
if (commits == null) return;
void GitActions.Commit.showDetailsView(commits[0], {
pin: false,
preserveFocus: true,
preserveVisibility: this._firstSelection
? this._showDetailsView === false
: this._showDetailsView !== 'selection',
});
this.container.events.fire(
'commit:selected',
{
commit: commits[0],
pin: false,
preserveFocus: true,
preserveVisibility: this._firstSelection
? this._showDetailsView === false
: this._showDetailsView !== 'selection',
},
{
source: this.id,
},
);
this._firstSelection = false;
}

+ 29
- 3
src/plus/webviews/timeline/timelineWebviewView.ts View File

@ -1,10 +1,10 @@
'use strict';
import type { Disposable, TextEditor } from 'vscode';
import { commands, Uri, window } from 'vscode';
import { GitActions } from '../../../commands/gitCommands.actions';
import { configuration } from '../../../configuration';
import { Commands, ContextKeys } from '../../../constants';
import type { Container } from '../../../container';
import type { EventBusPackage } from '../../../eventBus';
import { PlusFeatures } from '../../../features';
import type { RepositoriesChangeEvent } from '../../../git/gitProviderService';
import { GitUri } from '../../../git/gitUri';
@ -83,6 +83,7 @@ export class TimelineWebviewView extends WebviewViewBase {
return [
this.container.subscription.onDidChange(this.onSubscriptionChanged, this),
window.onDidChangeActiveTextEditor(debounce(this.onActiveEditorChanged, 250), this),
this.container.events.on('file:selected', this.onFileSelected, this),
this.container.git.onDidChangeRepository(this.onRepositoryChanged, this),
this.container.git.onDidChangeRepositories(this.onRepositoriesChanged, this),
];
@ -133,7 +134,13 @@ export class TimelineWebviewView extends WebviewViewBase {
const commit = await repository.getCommit(params.data.id);
if (commit == null) return;
void GitActions.Commit.showDetailsView(commit, { pin: false, preserveFocus: true });
this.container.events.fire(
'commit:selected',
{
commit: commit,
},
{ source: this.id },
);
});
break;
@ -165,6 +172,23 @@ export class TimelineWebviewView extends WebviewViewBase {
}
@debug({ args: false })
private onFileSelected(event: EventBusPackage) {
if (event.data == null) return;
let uri: Uri | undefined = event.data as Uri;
if (uri != null) {
if (!this.container.git.isTrackable(uri)) {
uri = undefined;
}
}
if (!this.updatePendingUri(uri)) return;
this.updateState();
}
@debug({ args: false })
private onRepositoriesChanged(e: RepositoriesChangeEvent) {
const changed = this.updatePendingUri(this._context.uri);
@ -371,7 +395,9 @@ export class TimelineWebviewView extends WebviewViewBase {
private updateState(immediate: boolean = false) {
if (!this.isReady || !this.visible) return;
this.updatePendingEditor(window.activeTextEditor);
if (this._pendingContext == null) {
this.updatePendingEditor(window.activeTextEditor);
}
if (immediate) {
void this.notifyDidChangeState();

+ 39
- 1
src/views/commitsView.ts View File

@ -1,4 +1,9 @@
import type { CancellationToken, ConfigurationChangeEvent } from 'vscode';
import type {
CancellationToken,
ConfigurationChangeEvent,
TreeViewSelectionChangeEvent,
TreeViewVisibilityChangeEvent,
} from 'vscode';
import { Disposable, ProgressLocation, ThemeIcon, TreeItem, TreeItemCollapsibleState, window } from 'vscode';
import type { CommitsViewConfig } from '../configuration';
import { configuration, ViewFilesLayout, ViewShowBranchComparison } from '../configuration';
@ -19,7 +24,10 @@ import { disposableInterval } from '../system/function';
import type { UsageChangeEvent } from '../usageTracker';
import { BranchNode } from './nodes/branchNode';
import { BranchTrackingStatusNode } from './nodes/branchTrackingStatusNode';
import { CommitFileNode } from './nodes/commitFileNode';
import { CommitNode } from './nodes/commitNode';
import { CommandMessageNode } from './nodes/common';
import { FileRevisionAsCommitNode } from './nodes/fileRevisionAsCommitNode';
import { RepositoryNode } from './nodes/repositoryNode';
import type { ViewNode } from './nodes/viewNode';
import { RepositoriesSubscribeableNode, RepositoryFolderNode } from './nodes/viewNode';
@ -288,6 +296,36 @@ export class CommitsView extends ViewBase {
return true;
}
protected override onSelectionChanged(e: TreeViewSelectionChangeEvent<ViewNode>) {
super.onSelectionChanged(e);
this.notifySelections();
}
protected override onVisibilityChanged(e: TreeViewVisibilityChangeEvent) {
super.onVisibilityChanged(e);
if (e.visible) {
this.notifySelections();
}
}
private notifySelections() {
const node = this.selection?.[0];
if (
node != null &&
(node instanceof CommitNode || node instanceof FileRevisionAsCommitNode || node instanceof CommitFileNode)
) {
this.container.events.fire(
'commit:selected',
{
commit: node.commit,
},
{ source: this.id },
);
}
}
async findCommit(commit: GitCommit | { repoPath: string; ref: string }, token?: CancellationToken) {
const repoNodeId = RepositoryNode.getId(commit.repoPath);

+ 34
- 1
src/views/stashesView.ts View File

@ -1,4 +1,10 @@
import type { CancellationToken, ConfigurationChangeEvent, Disposable } from 'vscode';
import type {
CancellationToken,
ConfigurationChangeEvent,
Disposable,
TreeViewSelectionChangeEvent,
TreeViewVisibilityChangeEvent,
} from 'vscode';
import { ProgressLocation, TreeItem, TreeItemCollapsibleState, window } from 'vscode';
import type { StashesViewConfig } from '../configuration';
import { configuration, ViewFilesLayout } from '../configuration';
@ -13,6 +19,7 @@ import { executeCommand } from '../system/command';
import { gate } from '../system/decorators/gate';
import { RepositoryNode } from './nodes/repositoryNode';
import { StashesNode } from './nodes/stashesNode';
import { StashFileNode } from './nodes/stashFileNode';
import { StashNode } from './nodes/stashNode';
import type { ViewNode } from './nodes/viewNode';
import { RepositoriesSubscribeableNode, RepositoryFolderNode } from './nodes/viewNode';
@ -149,6 +156,32 @@ export class StashesView extends ViewBase {
return true;
}
protected override onSelectionChanged(e: TreeViewSelectionChangeEvent<ViewNode>) {
super.onSelectionChanged(e);
this.notifySelections();
}
protected override onVisibilityChanged(e: TreeViewVisibilityChangeEvent) {
super.onVisibilityChanged(e);
if (e.visible) {
this.notifySelections();
}
}
private notifySelections() {
const node = this.selection?.[0];
if (node != null && (node instanceof StashNode || node instanceof StashFileNode)) {
this.container.events.fire(
'commit:selected',
{
commit: node.commit,
},
{ source: this.id },
);
}
}
findStash(stash: GitStashReference, token?: CancellationToken) {
const repoNodeId = RepositoryNode.getId(stash.repoPath);

+ 11
- 51
src/webviews/commitDetails/commitDetailsWebviewView.ts View File

@ -1,10 +1,4 @@
import type {
CancellationToken,
ConfigurationChangeEvent,
TextDocumentShowOptions,
TreeViewSelectionChangeEvent,
TreeViewVisibilityChangeEvent,
} from 'vscode';
import type { CancellationToken, ConfigurationChangeEvent, TextDocumentShowOptions } from 'vscode';
import { CancellationTokenSource, Disposable, Uri, ViewColumn, window } from 'vscode';
import { serializeAutolink } from '../../annotations/autolinks';
import type { CopyShaToClipboardCommandArgs } from '../../commands';
@ -13,6 +7,7 @@ import { configuration } from '../../configuration';
import { Commands, ContextKeys, CoreCommands } from '../../constants';
import type { Container } from '../../container';
import { getContext } from '../../context';
import type { EventBusPackage } from '../../eventBus';
import { CommitFormatter } from '../../git/formatters/commitFormatter';
import type { GitCommit } from '../../git/models/commit';
import { isCommit } from '../../git/models/commit';
@ -43,7 +38,6 @@ import { CommitNode } from '../../views/nodes/commitNode';
import { FileRevisionAsCommitNode } from '../../views/nodes/fileRevisionAsCommitNode';
import { StashFileNode } from '../../views/nodes/stashFileNode';
import { StashNode } from '../../views/nodes/stashNode';
import type { ViewNode } from '../../views/nodes/viewNode';
import type { IpcMessage } from '../protocol';
import { onIpc } from '../protocol';
import { WebviewViewBase } from '../webviewViewBase';
@ -117,6 +111,12 @@ export class CommitDetailsWebviewView extends WebviewViewBase
);
}
onCommitSelected(event: EventBusPackage) {
if (event.data == null) return;
void this.show(event.data);
}
@log<CommitDetailsWebviewView['show']>({
args: {
0: o =>
@ -253,13 +253,10 @@ export class CommitDetailsWebviewView extends WebviewViewBase
if (this._pinned || !this.visible) return;
const { lineTracker, commitsView, stashesView } = this.container;
const { lineTracker } = this.container;
this._visibilityDisposable = Disposable.from(
lineTracker.subscribe(this, lineTracker.onDidChangeActiveLines(this.onActiveLinesChanged, this)),
commitsView.onDidChangeSelection(this.onCommitsViewSelectionChanged, this),
commitsView.onDidChangeVisibility(this.onCommitsViewVisibilityChanged, this),
stashesView.onDidChangeSelection(this.onStashesViewSelectionChanged, this),
stashesView.onDidChangeVisibility(this.onStashesViewVisibilityChanged, this),
this.container.events.on('commit:selected', debounce(this.onCommitSelected, 250), this),
);
const commit = this._pendingContext?.commit ?? this.getBestCommitOrStash();
@ -355,44 +352,6 @@ export class CommitDetailsWebviewView extends WebviewViewBase
this.updateCommit(commit);
}
private onCommitsViewSelectionChanged(e: TreeViewSelectionChangeEvent<ViewNode>) {
const node = e.selection?.[0];
if (
node != null &&
(node instanceof CommitNode || node instanceof FileRevisionAsCommitNode || node instanceof CommitFileNode)
) {
this.updateCommit(node.commit);
}
}
private onCommitsViewVisibilityChanged(e: TreeViewVisibilityChangeEvent) {
if (!e.visible) return;
const node = this.container.commitsView.activeSelection;
if (
node != null &&
(node instanceof CommitNode || node instanceof FileRevisionAsCommitNode || node instanceof CommitFileNode)
) {
this.updateCommit(node.commit);
}
}
private onStashesViewSelectionChanged(e: TreeViewSelectionChangeEvent<ViewNode>) {
const node = e.selection?.[0];
if (node != null && (node instanceof StashNode || node instanceof StashFileNode)) {
this.updateCommit(node.commit);
}
}
private onStashesViewVisibilityChanged(e: TreeViewVisibilityChangeEvent) {
if (!e.visible) return;
const node = this.container.stashesView.activeSelection;
if (node != null && (node instanceof StashNode || node instanceof StashFileNode)) {
this.updateCommit(node.commit);
}
}
private _cancellationTokenSource: CancellationTokenSource | undefined = undefined;
@debug({ args: false })
@ -865,6 +824,7 @@ export class CommitDetailsWebviewView extends WebviewViewBase
preview: true,
...this.getShowOptions(params),
});
this.container.events.fire('file:selected', file.uri, { source: this.id });
}
private async openFile(params: FileActionParams) {

+ 14
- 6
src/webviews/rebase/rebaseEditor.ts View File

@ -8,7 +8,6 @@ import type {
import { ConfigurationTarget, Disposable, Position, Range, Uri, window, workspace, WorkspaceEdit } from 'vscode';
import { getNonce } from '@env/crypto';
import { ShowCommitsInViewCommand } from '../../commands';
import { GitActions } from '../../commands/gitCommands.actions';
import { configuration } from '../../configuration';
import { ContextKeys, CoreCommands } from '../../constants';
import type { Container } from '../../container';
@ -512,11 +511,20 @@ export class RebaseEditorProvider implements CustomTextEditorProvider, Disposabl
// Find the full sha
sha = context.commits?.find(c => c.sha.startsWith(sha!))?.sha ?? sha;
void GitActions.Commit.showDetailsView(GitReference.create(sha, context.repoPath, { refType: 'revision' }), {
pin: false,
preserveFocus: true,
preserveVisibility: context.firstSelection ? showDetailsView === false : showDetailsView !== 'selection',
});
this.container.events.fire(
'commit:selected',
{
commit: GitReference.create(sha, context.repoPath, { refType: 'revision' }),
pin: false,
preserveFocus: true,
preserveVisibility: context.firstSelection
? showDetailsView === false
: showDetailsView !== 'selection',
},
{
source: 'gitlens.rebase',
},
);
context.firstSelection = false;
}

Loading…
Cancel
Save