Browse Source

Reworks Commit Details commit pinning

- Never implicitly pins
 - "Soft" pins on file interaction (resets on focus or commit change)
main
Eric Amodio 1 year ago
parent
commit
b4d23c663a
7 changed files with 76 additions and 40 deletions
  1. +1
    -1
      src/eventBus.ts
  2. +12
    -2
      src/plus/webviews/graph/graphWebview.ts
  3. +3
    -3
      src/plus/webviews/timeline/timelineWebview.ts
  4. +1
    -1
      src/views/commitsView.ts
  5. +1
    -1
      src/views/stashesView.ts
  6. +54
    -32
      src/webviews/commitDetails/commitDetailsWebview.ts
  7. +4
    -0
      src/webviews/webviewsController.ts

+ 1
- 1
src/eventBus.ts View File

@ -9,7 +9,7 @@ import type { WebviewIds, WebviewViewIds } from './webviews/webviewsController';
export type CommitSelectedEvent = EventBusEvent<'commit:selected'>;
interface CommitSelectedEventArgs {
readonly commit: GitRevisionReference | GitCommit;
readonly pin?: boolean;
readonly interaction: 'active' | 'passive';
readonly preserveFocus?: boolean;
readonly preserveVisibility?: boolean;
}

+ 12
- 2
src/plus/webviews/graph/graphWebview.ts View File

@ -15,6 +15,7 @@ import type { Config } from '../../../config';
import { Commands, ContextKeys, CoreCommands, CoreGitCommands, GlyphChars } from '../../../constants';
import type { Container } from '../../../container';
import { getContext, onDidChangeContext } from '../../../context';
import type { CommitSelectedEvent } from '../../../eventBus';
import { PlusFeatures } from '../../../features';
import * as BranchActions from '../../../git/actions/branch';
import * as ContributorActions from '../../../git/actions/contributor';
@ -517,7 +518,7 @@ export class GraphWebviewProvider implements WebviewProvider {
'commit:selected',
{
commit: activeSelection,
pin: false,
interaction: 'passive',
preserveFocus: true,
preserveVisibility: this._showDetailsView === false,
},
@ -688,6 +689,7 @@ export class GraphWebviewProvider implements WebviewProvider {
'commit:selected',
{
commit: commit,
interaction: 'active',
preserveFocus: e.preserveFocus,
preserveVisibility: false,
},
@ -695,6 +697,14 @@ export class GraphWebviewProvider implements WebviewProvider {
source: this.id,
},
);
if (!this.container.commitDetailsView.loaded) {
void this.container.commitDetailsView.show({ preserveFocus: e.preserveFocus }, {
commit: commit,
interaction: 'active',
preserveVisibility: false,
} satisfies CommitSelectedEvent['data']);
}
}
}
@ -1046,7 +1056,7 @@ export class GraphWebviewProvider implements WebviewProvider {
'commit:selected',
{
commit: commits[0],
pin: false,
interaction: 'passive',
preserveFocus: true,
preserveVisibility: this._firstSelection
? this._showDetailsView === false

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

@ -158,9 +158,9 @@ export class TimelineWebviewProvider implements WebviewProvider {
'commit:selected',
{
commit: commit,
pin: false,
preserveFocus: false,
preserveVisibility: false,
interaction: 'passive',
preserveFocus: true,
preserveVisibility: true,
},
{ source: this.id },
);

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

@ -319,7 +319,7 @@ export class CommitsView extends ViewBase {
'commit:selected',
{
commit: node.commit,
pin: false,
interaction: 'passive',
preserveFocus: true,
preserveVisibility: true,
},

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

@ -178,7 +178,7 @@ export class StashesView extends ViewBase {
'commit:selected',
{
commit: node.commit,
pin: false,
interaction: 'passive',
preserveFocus: true,
preserveVisibility: true,
},

+ 54
- 32
src/webviews/commitDetails/commitDetailsWebview.ts View File

@ -85,6 +85,7 @@ export class CommitDetailsWebviewProvider implements WebviewProvider
private _pendingContext: Partial<Context> | undefined;
private readonly _disposable: Disposable;
private _pinned = false;
private _focused = false;
constructor(
readonly container: Container,
@ -129,33 +130,33 @@ export class CommitDetailsWebviewProvider implements WebviewProvider
data = undefined;
}
if (this._pinned && !data?.pin && this.host.visible) return false;
let commit;
let pin;
if (data != null) {
if (data.preserveFocus) {
options.preserveFocus = true;
}
({ commit, pin, ...data } = data);
({ commit, ...data } = data);
}
if (commit == null) {
if (this._pinned) return false;
commit = this.getBestCommitOrStash();
}
if (commit != null && !this._context.commit?.ref.startsWith(commit.ref)) {
await this.updateCommit(commit, { pinned: pin ?? false });
await this.updateCommit(commit, { pinned: false });
}
if (data?.preserveVisibility) return false;
if (data?.preserveVisibility && !this.host.visible) return false;
return true;
}
private onCommitSelected(e: CommitSelectedEvent) {
if (e.data == null) return;
if (this._pinned && e.data.interaction === 'passive') return;
void this.canShowWebviewView(false, { preserveFocus: e.data.preserveFocus }, e.data);
void this.host.show(false, { preserveFocus: e.data.preserveFocus }, e.data);
}
includeBootstrap(): Promise<Serialized<State>> {
@ -167,7 +168,15 @@ export class CommitDetailsWebviewProvider implements WebviewProvider
return this.getState(this._context);
}
private _visibilityDisposable: Disposable | undefined;
onFocusChanged(focused: boolean): void {
if (this._focused === focused) return;
this._focused = focused;
if (focused && this.isLineTrackerSuspended) {
this.ensureTrackers();
}
}
onVisibilityChanged(visible: boolean) {
this.ensureTrackers();
if (!visible) return;
@ -229,21 +238,39 @@ export class CommitDetailsWebviewProvider implements WebviewProvider
}
}
private _commitTrackerDisposable: Disposable | undefined;
private _lineTrackerDisposable: Disposable | undefined;
private ensureTrackers(): void {
this._visibilityDisposable?.dispose();
this._visibilityDisposable = undefined;
this._commitTrackerDisposable?.dispose();
this._commitTrackerDisposable = undefined;
this._lineTrackerDisposable?.dispose();
this._lineTrackerDisposable = undefined;
if (this._pinned || !this.host.visible) return;
this._commitTrackerDisposable = this.container.events.on(
'commit:selected',
debounce(this.onCommitSelected, 250),
this,
);
const { lineTracker } = this.container;
this._visibilityDisposable = Disposable.from(
this.container.events.on('commit:selected', debounce(this.onCommitSelected, 250), this),
lineTracker.subscribe(this, lineTracker.onDidChangeActiveLines(this.onActiveLinesChanged, this)),
this._lineTrackerDisposable = lineTracker.subscribe(
this,
lineTracker.onDidChangeActiveLines(this.onActiveEditorLinesChanged, this),
);
}
onReady(): void {
this.updateState(false);
private get isLineTrackerSuspended() {
return this._lineTrackerDisposable == null;
}
private suspendLineTracker() {
// Defers the suspension of the line tracker, so that the focus change event can be handled first
setTimeout(() => {
this._lineTrackerDisposable?.dispose();
this._lineTrackerDisposable = undefined;
}, 100);
}
onRefresh(_force?: boolean | undefined): void {
@ -320,21 +347,12 @@ export class CommitDetailsWebviewProvider implements WebviewProvider
}
}
private onActiveLinesChanged(e: LinesChangeEvent) {
if (e.pending) return;
private onActiveEditorLinesChanged(e: LinesChangeEvent) {
if (e.pending || e.editor == null) return;
let commit;
if (e.editor == null) {
if (getContext('gitlens:webview:graph:active') || getContext('gitlens:webview:rebaseEditor:active')) {
commit = this._pendingContext?.commit ?? this._context.commit;
if (commit == null) return;
}
}
const line = e.selections?.[0]?.active;
const commit = line != null ? this.container.lineTracker.getState(line)?.commit : undefined;
if (commit == null) {
commit =
e.selections != null ? this.container.lineTracker.getState(e.selections[0].active)?.commit : undefined;
}
void this.updateCommit(commit);
}
@ -485,6 +503,10 @@ export class CommitDetailsWebviewProvider implements WebviewProvider
this.updatePinned(options?.pinned);
}
if (this.isLineTrackerSuspended) {
this.ensureTrackers();
}
this.updateState(options?.immediate ?? true);
}
@ -777,7 +799,7 @@ export class CommitDetailsWebviewProvider implements WebviewProvider
const [commit, file] = result;
this.updatePinned(true, true);
this.suspendLineTracker();
void showDetailsQuickPick(commit, file);
}
@ -787,7 +809,7 @@ export class CommitDetailsWebviewProvider implements WebviewProvider
const [commit, file] = result;
this.updatePinned(true, true);
this.suspendLineTracker();
void openChangesWithWorking(file.path, commit, {
preserveFocus: true,
preview: true,
@ -801,7 +823,7 @@ export class CommitDetailsWebviewProvider implements WebviewProvider
const [commit, file] = result;
this.updatePinned(true, true);
this.suspendLineTracker();
void openChanges(file.path, commit, {
preserveFocus: true,
preview: true,
@ -816,7 +838,7 @@ export class CommitDetailsWebviewProvider implements WebviewProvider
const [commit, file] = result;
this.updatePinned(true, true);
this.suspendLineTracker();
void openFile(file.path, commit, {
preserveFocus: true,
preview: true,

+ 4
- 0
src/webviews/webviewsController.ts View File

@ -60,6 +60,7 @@ interface WebviewViewMetadata {
export interface WebviewViewProxy extends Disposable {
readonly id: string;
readonly loaded: boolean;
readonly visible: boolean;
refresh(force?: boolean): Promise<void>;
show(options?: { preserveFocus?: boolean }, ...args: unknown[]): Promise<void>;
@ -138,6 +139,9 @@ export class WebviewsController implements Disposable {
this.disposables.push(disposable);
return {
id: id,
get loaded() {
return metadata.webview != null;
},
get visible() {
return metadata.webview?.visible ?? false;
},

Loading…
Cancel
Save