Skip to content

Commit

Permalink
Fixes #242 - line annotation state isn't preserved properly
Browse files Browse the repository at this point in the history
  • Loading branch information
eamodio committed Jan 15, 2018
1 parent 7ff3ae9 commit 077cb6e
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 20 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).

## [7.5.2] - 2018-01-15
### Fixed
- Fixes [#242](https://github.com/eamodio/vscode-gitlens/issues/242) - Broken "gitlens.blame.line.enabled" setting

## [7.5.1] - 2018-01-15
### Added
- Adds [Gravatar](https://en.gravatar.com/) support to gutter and hover blame annotations
Expand Down
114 changes: 94 additions & 20 deletions src/currentLineController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,55 @@ export enum LineAnnotationType {
Hover = 'hover'
}

class AnnotationState {

constructor(private _enabled: boolean, private _annotationType: LineAnnotationType) { }

get annotationType(): LineAnnotationType {
return this._annotationType;
}

get enabled(): boolean {
return this.suspended ? false : this._enabled;
}

private _suspendReason?: 'debugging' | 'dirty';
get suspended(): boolean {
return this._suspendReason !== undefined;
}

reset(enabled: boolean, annotationType: LineAnnotationType): boolean {
// returns whether or not a refresh is required

if (this._enabled === enabled && this._annotationType === annotationType && !this.suspended) return false;

this._enabled = enabled;
this._annotationType = annotationType;
this._suspendReason = undefined;

return true;
}

resume(reason: 'debugging' | 'dirty'): boolean {
// returns whether or not a refresh is required

const refresh = this._suspendReason !== undefined;
this._suspendReason = undefined;
return refresh;
}

suspend(reason: 'debugging' | 'dirty'): boolean {
// returns whether or not a refresh is required

const refresh = this._suspendReason === undefined;
this._suspendReason = reason;
return refresh;
}
}

export class CurrentLineController extends Disposable {

private _blameAnnotationState: { enabled: boolean, annotationType: LineAnnotationType, reason: 'user' | 'debugging' | 'dirty' } | undefined;
private _blameAnnotationState: AnnotationState | undefined;
private _editor: TextEditor | undefined;
private _lineTracker: LineTracker<GitLineState>;
private _statusBarItem: StatusBarItem | undefined;
Expand Down Expand Up @@ -149,11 +195,9 @@ export class CurrentLineController extends Disposable {
}

private onDebugSessionStarted() {
const state = this.getBlameAnnotationState();
if (!state.enabled) return;

this._debugSessionEndDisposable = debug.onDidTerminateDebugSession(this.onDebugSessionEnded, this);
this.setBlameAnnotationState(false, window.activeTextEditor, 'debugging');
if (this.suspendBlameAnnotations('debugging', window.activeTextEditor)) {
this._debugSessionEndDisposable = debug.onDidTerminateDebugSession(this.onDebugSessionEnded, this);
}
}

private onDebugSessionEnded() {
Expand All @@ -162,18 +206,23 @@ export class CurrentLineController extends Disposable {
this._debugSessionEndDisposable = undefined;
}

this.setBlameAnnotationState(true, window.activeTextEditor, 'debugging');
this.resumeBlameAnnotations('debugging', window.activeTextEditor);
}

private onDirtyIdleTriggered(e: DocumentDirtyIdleTriggerEvent<GitDocumentState>) {
const maxLines = configuration.get<number>(configuration.name('advanced')('blame')('sizeThresholdAfterEdit').value);
if (maxLines > 0 && e.document.document.lineCount > maxLines) return;

this.setBlameAnnotationState(true, window.activeTextEditor, 'dirty');
this.resumeBlameAnnotations('dirty', window.activeTextEditor);
}

private async onDirtyStateChanged(e: DocumentDirtyStateChangeEvent<GitDocumentState>) {
this.setBlameAnnotationState(!e.dirty, window.activeTextEditor, 'dirty', { force: true });
if (e.dirty) {
this.suspendBlameAnnotations('dirty', window.activeTextEditor);
}
else {
this.resumeBlameAnnotations('dirty', window.activeTextEditor, { force: true });
}
}

private onFileAnnotationsToggled() {
Expand Down Expand Up @@ -280,31 +329,56 @@ export class CurrentLineController extends Disposable {
}

async showAnnotations(editor: TextEditor | undefined, type: LineAnnotationType) {
this.setBlameAnnotationState(true, editor, 'user', { type: type });
this.setBlameAnnotationState(true, type, editor);
}

async toggleAnnotations(editor: TextEditor | undefined, type: LineAnnotationType) {
if (editor === undefined) return;

const state = this.getBlameAnnotationState();
this.setBlameAnnotationState(!state.enabled, editor, 'user', { type: type });
this.setBlameAnnotationState(!state.enabled, type, editor);
}

private async setBlameAnnotationState(enabled: boolean, editor: TextEditor | undefined, reason: 'user' | 'debugging' | 'dirty', options: { force?: boolean, type?: LineAnnotationType } = {}) {
if (editor === undefined) return;
private async resumeBlameAnnotations(reason: 'debugging' | 'dirty', editor: TextEditor | undefined, options: { force?: boolean } = {}) {
if (!options.force && (this._blameAnnotationState === undefined || !this._blameAnnotationState.suspended)) return;

let refresh = false;
if (this._blameAnnotationState !== undefined) {
refresh = this._blameAnnotationState.resume(reason);
}

// If we are trying to turn annotations on, check if it was the user, or a matching reason
if (enabled && reason !== 'user' && reason !== (this._blameAnnotationState && this._blameAnnotationState.reason)) return;
if (editor === undefined || (!options.force && !refresh)) return;

await this.refresh(editor);
}

private async suspendBlameAnnotations(reason: 'debugging' | 'dirty', editor: TextEditor | undefined, options: { force?: boolean } = {}) {
const state = this.getBlameAnnotationState();
if (options.type === undefined) {
options.type = state.annotationType;

// If we aren't enabled, suspend doesn't matter
if (this._blameAnnotationState === undefined && !state.enabled) return false;

if (this._blameAnnotationState === undefined) {
this._blameAnnotationState = new AnnotationState(state.enabled, state.annotationType);
}
const refresh = this._blameAnnotationState.suspend(reason);

if (editor === undefined || (!options.force && !refresh)) return;

await this.refresh(editor);
return true;
}

// If we are off and want it off or we are on and want it on with matching annotation type
if (!options.force && state.enabled === enabled && (!enabled || state.annotationType === options.type)) return;
private async setBlameAnnotationState(enabled: boolean, type: LineAnnotationType, editor: TextEditor | undefined) {
let refresh = true;
if (this._blameAnnotationState === undefined) {
this._blameAnnotationState = new AnnotationState(enabled, type);
}
else {
refresh = this._blameAnnotationState.reset(enabled, type);
}

this._blameAnnotationState = { enabled: enabled, annotationType: options.type, reason: reason };
if (editor === undefined || !refresh) return;

await this.refresh(editor);
}
Expand Down

0 comments on commit 077cb6e

Please sign in to comment.