Browse Source

Adds avatars to gutter and hover blame annotations

main
Eric Amodio 6 years ago
parent
commit
536cae05f3
17 changed files with 163 additions and 103 deletions
  1. +4
    -0
      CHANGELOG.md
  2. +3
    -3
      README.md
  3. +20
    -28
      package.json
  4. +32
    -16
      src/annotations/annotationProvider.ts
  5. +1
    -1
      src/annotations/annotations.ts
  6. +3
    -3
      src/annotations/blameAnnotationProvider.ts
  7. +50
    -12
      src/annotations/gutterBlameAnnotationProvider.ts
  8. +5
    -5
      src/annotations/heatmapBlameAnnotationProvider.ts
  9. +5
    -5
      src/annotations/hoverBlameAnnotationProvider.ts
  10. +4
    -4
      src/annotations/recentChangesAnnotationProvider.ts
  11. +8
    -2
      src/configuration.ts
  12. +15
    -2
      src/extension.ts
  13. +4
    -4
      src/git/models/commit.ts
  14. +1
    -2
      src/views/commitFileNode.ts
  15. +2
    -2
      src/views/commitNode.ts
  16. +3
    -7
      src/views/gitExplorer.ts
  17. +3
    -7
      src/views/resultsExplorer.ts

+ 4
- 0
CHANGELOG.md View File

@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
## [7.3.0-beta4] - 2018-01-11
### Added
- Adds [Gravatar](https://en.gravatar.com/) support to gutter and hover blame annotations
- Adds `gitlens.annotations.file.gutter.gravatars` setting to specify whether or not to show gravatar images in the gutter blame annotations
- Adds support for providing blame annotations, code lens, etc on files with unsaved changes -- closes [#112](https://github.com/eamodio/vscode-gitlens/issues/112)
- Adds `gitlens.defaultDateStyle` setting to specify how dates will be displayed by default -- closes [#89](https://github.com/eamodio/vscode-gitlens/issues/89)
- Adds *Compare with Working* command (`gitlens.explorers.compareWithWorking`) to branch, tag, and revision (commit) nodes in the **GitLens** view to compare the current selection with the current working tree in the **GitLens Results** view
@ -26,6 +28,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Renames *Open Changes with Working Tree* command (`gitlens.openChangesWithWorking`) to *Open Changes with Working File*
- Renames *Compare Selected Ancestor with Working* command (`gitlens.compareSelectedAncestorWithWorking`) to *Compare Selected Ancestor with Working Tree*
- Renames *Compare with Working* command (`gitlens.compareWithWorking`) to *Compare with Working Tree*
- Deprecates `gitlens.gitExplorer.gravatarsDefault` setting, replaced by `gitlens.defaultGravatarsStyle`
- Deprecates `gitlens.resultsExplorer.gravatarsDefault` setting, replaced by `gitlens.defaultGravatarsStyle`
### Fixed
- Fixes issue where the **GitLens Results** view wouldn't properly update when replacing existing results

+ 3
- 3
README.md View File

@ -387,6 +387,7 @@ GitLens is highly customizable and provides many configuration settings to allow
|-----|------------
|`gitlens.defaultDateFormat`|Specifies how absolute dates will be formatted by default<br />See https://momentjs.com/docs/#/displaying/format/ for valid formats
|`gitlens.defaultDateStyle`|Specifies how dates will be displayed by default
|`gitlens.defaultGravatarsStyle`|Specifies the style of the gravatar default (fallback) images<br />`identicon` - a geometric pattern<br />`mm` - (mystery-man) a simple, cartoon-style silhouetted outline of a person (does not vary by email hash)<br />`monsterid` - a monster with different colors, faces, etc<br />`retro` - 8-bit arcade-style pixelated faces<br />`robohash` - a robot with different colors, faces, etc<br />`wavatar` - faces with differing features and backgrounds
|`gitlens.insiders`|Opts into the insiders channel -- provides access to upcoming features
|`gitlens.keymap`|Specifies the keymap to use for GitLens shortcut keys<br />`standard` - adds a standard set of shortcut keys<br />`chorded` - adds a chorded set of shortcut keys that all start with `Ctrl+Alt+G` (`⌥⌘G` on macOS)<br />`none` - no shortcut keys will be added
|`gitlens.outputLevel`|Specifies how much (if any) output will be sent to the GitLens output channel
@ -407,6 +408,7 @@ GitLens is highly customizable and provides many configuration settings to allow
|`gitlens.annotations.file.gutter.format`|Specifies the format of the gutter blame annotations<br />Available tokens<br />`${id}` - commit id<br />`${author}` - commit author<br />`${message}` - commit message<br />`${ago}` - relative commit date (e.g. 1 day ago)<br />`${date}` - formatted commit date (format specified by `gitlens.annotations.file.gutter.dateFormat`)<br />`${authorAgo}` - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|`gitlens.annotations.file.gutter.dateFormat`|Specifies how to format absolute dates (using the `${date}` token) in gutter blame annotations<br />See https://momentjs.com/docs/#/displaying/format/ for valid formats
|`gitlens.annotations.file.gutter.compact`|Specifies whether or not to compact (deduplicate) matching adjacent gutter blame annotations
|`gitlens.annotations.file.gutter.gravatars`|Specifies whether or not to show gravatar images in the gutter blame annotations
|`gitlens.annotations.file.gutter.heatmap.enabled`|Specifies whether or not to provide a heatmap indicator in the gutter blame annotations
|`gitlens.annotations.file.gutter.heatmap.location`|Specifies where the heatmap indicators will be shown in the gutter blame annotations<br />`left` - adds a heatmap indicator on the left edge of the gutter blame annotations<br />`right` - adds a heatmap indicator on the right edge of the gutter blame annotations
|`gitlens.annotations.file.gutter.hover.details`|Specifies whether or not to provide a commit details hover annotation over the gutter blame annotations
@ -465,7 +467,6 @@ GitLens is highly customizable and provides many configuration settings to allow
|`gitlens.gitExplorer.commitFormat`|Specifies the format of committed changes in the **GitLens** view<br />Available tokens<br /> ${id} - commit id<br /> ${author} - commit author<br /> ${message} - commit message<br /> ${ago} - relative commit date (e.g. 1 day ago)<br /> ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)<br /> ${authorAgo} - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|`gitlens.gitExplorer.commitFileFormat`|Specifies the format of a committed file in the **GitLens** view<br />Available tokens<br /> ${directory} - directory name<br /> ${file} - file name<br /> ${filePath} - formatted file name and path<br /> ${path} - full file path
|`gitlens.gitExplorer.gravatars`|Specifies whether or not to show gravatar images instead of commit (or status) icons in the **GitLens** view
|`gitlens.gitExplorer.gravatarsDefault`|Specifies the style of the gravatar default (fallback) images in the **GitLens** view<br />`identicon` - a geometric pattern<br />`mm` - (mystery-man) a simple, cartoon-style silhouetted outline of a person (does not vary by email hash)<br />`monsterid` - a monster with different colors, faces, etc<br />`retro` - 8-bit arcade-style pixelated faces<br />`robohash` - a robot with different colors, faces, etc<br />`wavatar` - faces with differing features and backgrounds
|`gitlens.gitExplorer.includeWorkingTree`|Specifies whether or not to include working tree files inside the `Repository Status` node of the **GitLens** view
|`gitlens.gitExplorer.showTrackingBranch`|Specifies whether or not to show the tracking branch when displaying local branches in the **GitLens** view"
|`gitlens.gitExplorer.stashFormat`|Specifies the format of stashed changes in the **GitLens** view<br />Available tokens<br /> ${id} - commit id<br /> ${author} - commit author<br /> ${message} - commit message<br /> ${ago} - relative commit date (e.g. 1 day ago)<br /> ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)<br /> ${authorAgo} - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
@ -482,7 +483,6 @@ GitLens is highly customizable and provides many configuration settings to allow
|`gitlens.resultsExplorer.commitFormat`|Specifies the format of committed changes in the **GitLens Results** view<br />Available tokens<br /> ${id} - commit id<br /> ${author} - commit author<br /> ${message} - commit message<br /> ${ago} - relative commit date (e.g. 1 day ago)<br /> ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)<br /> ${authorAgo} - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|`gitlens.resultsExplorer.commitFileFormat`|Specifies the format of a committed file in the **GitLens Results** view<br />Available tokens<br /> ${directory} - directory name<br /> ${file} - file name<br /> ${filePath} - formatted file name and path<br /> ${path} - full file path
|`gitlens.resultsExplorer.gravatars`|Specifies whether or not to show gravatar images instead of commit (or status) icons in the **GitLens Results** view
|`gitlens.resultsExplorer.gravatarsDefault`|Specifies the style of the gravatar default (fallback) images in the **GitLens Results** view<br />`identicon` - a geometric pattern<br />`mm` - (mystery-man) a simple, cartoon-style silhouetted outline of a person (does not vary by email hash)<br />`monsterid` - a monster with different colors, faces, etc<br />`retro` - 8-bit arcade-style pixelated faces<br />`robohash` - a robot with different colors, faces, etc<br />`wavatar` - faces with differing features and backgrounds
|`gitlens.resultsExplorer.showTrackingBranch`|Specifies whether or not to show the tracking branch when displaying local branches in the **GitLens Results** view"
|`gitlens.resultsExplorer.stashFormat`|Specifies the format of stashed changes in the **GitLens Results** view<br />Available tokens<br /> ${id} - commit id<br /> ${author} - commit author<br /> ${message} - commit message<br /> ${ago} - relative commit date (e.g. 1 day ago)<br /> ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)<br /> ${authorAgo} - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|`gitlens.resultsExplorer.stashFileFormat`|Specifies the format of a stashed file in the **GitLens Results** view<br />Available tokens<br /> ${directory} - directory name<br /> ${file} - file name<br /> ${filePath} - formatted file name and path<br /> ${path} - full file path
@ -516,10 +516,10 @@ GitLens is highly customizable and provides many configuration settings to allow
|Name | Description
|-----|------------
|`gitlens.advanced.git`|Specifies the git path to use
|`gitlens.advanced.blame.delayAfterEdit`|Specifies the time (in milliseconds) to wait before re-blaming an unsaved document after an edit. Use 0 to specify an infinite wait
|`gitlens.advanced.blame.sizeThresholdAfterEdit`|Specifies the maximum document size (in lines) allowed to be re-blamed after an edit while still unsaved. Use 0 to specify no maximum
|`gitlens.advanced.caching.enabled`|Specifies whether git output will be cached -- changing the default is not recommended
|`gitlens.advanced.git`|Specifies the git path to use
|`gitlens.advanced.maxListItems`|Specifies the maximum number of items to show in a list. Use 0 to specify no maximum
|`gitlens.advanced.menus`|Specifies which commands will be added to which menus
|`gitlens.advanced.messages`|Specifies which messages should be suppressed

+ 20
- 28
package.json View File

@ -102,6 +102,12 @@
"description": "Specifies whether or not to compact (deduplicate) matching adjacent gutter blame annotations",
"scope": "window"
},
"gitlens.annotations.file.gutter.gravatars": {
"type": "boolean",
"default": true,
"description": "Specifies whether or not to show gravatar images in the gutter blame annotations",
"scope": "window"
},
"gitlens.annotations.file.gutter.heatmap.enabled": {
"type": "boolean",
"default": true,
@ -488,6 +494,20 @@
"description": "Specifies how dates will be displayed by default",
"scope": "window"
},
"gitlens.defaultGravatarsStyle": {
"type": "string",
"default": "robohash",
"enum": [
"identicon",
"mm",
"monsterid",
"retro",
"robohash",
"wavatar"
],
"description": "Specifies the style of the gravatar default (fallback) images\n `identicon` - a geometric pattern\n `mm` - (mystery-man) a simple, cartoon-style silhouetted outline of a person (does not vary by email hash)\n `monsterid` - a monster with different colors, faces, etc\n `retro` - 8-bit arcade-style pixelated faces\n `robohash` - a robot with different colors, faces, etc\n `wavatar` - faces with differing features and backgrounds",
"scope": "window"
},
"gitlens.gitExplorer.autoRefresh": {
"type": "boolean",
"default": true,
@ -541,20 +561,6 @@
"description": "Specifies whether or not to show gravatar images instead of commit (or status) icons in the `GitLens` view",
"scope": "window"
},
"gitlens.gitExplorer.gravatarsDefault": {
"type": "string",
"default": "robohash",
"enum": [
"identicon",
"mm",
"monsterid",
"retro",
"robohash",
"wavatar"
],
"description": "Specifies the style of the gravatar default (fallback) images in the `GitLens` view\n `identicon` - a geometric pattern\n `mm` - (mystery-man) a simple, cartoon-style silhouetted outline of a person (does not vary by email hash)\n `monsterid` - a monster with different colors, faces, etc\n `retro` - 8-bit arcade-style pixelated faces\n `robohash` - a robot with different colors, faces, etc\n `wavatar` - faces with differing features and backgrounds",
"scope": "window"
},
"gitlens.gitExplorer.includeWorkingTree": {
"type": "boolean",
"default": true,
@ -730,20 +736,6 @@
"description": "Specifies whether or not to show gravatar images instead of commit (or status) icons in the `GitLens Results` view",
"scope": "window"
},
"gitlens.resultsExplorer.gravatarsDefault": {
"type": "string",
"default": "robohash",
"enum": [
"identicon",
"mm",
"monsterid",
"retro",
"robohash",
"wavatar"
],
"description": "Specifies the style of the gravatar default (fallback) images in the `GitLens Results` view\n `identicon` - a geometric pattern\n `mm` - (mystery-man) a simple, cartoon-style silhouetted outline of a person (does not vary by email hash)\n `monsterid` - a monster with different colors, faces, etc\n `retro` - 8-bit arcade-style pixelated faces\n `robohash` - a robot with different colors, faces, etc\n `wavatar` - faces with differing features and backgrounds",
"scope": "window"
},
"gitlens.resultsExplorer.showTrackingBranch": {
"type": "boolean",
"default": true,

+ 32
- 16
src/annotations/annotationProvider.ts View File

@ -17,21 +17,21 @@ export abstract class AnnotationProviderBase extends Disposable {
public correlationKey: TextEditorCorrelationKey;
public document: TextDocument;
protected _decorations: DecorationOptions[] | undefined;
protected _disposable: Disposable;
protected decorations: DecorationOptions[] | undefined;
protected disposable: Disposable;
constructor(
public editor: TextEditor,
protected readonly trackedDocument: TrackedDocument<GitDocumentState>,
protected _decoration: TextEditorDecorationType | undefined,
protected _highlightDecoration: TextEditorDecorationType | undefined
protected decoration: TextEditorDecorationType | undefined,
protected highlightDecoration: TextEditorDecorationType | undefined
) {
super(() => this.dispose());
this.correlationKey = AnnotationProviderBase.getCorrelationKey(this.editor);
this.document = this.editor.document;
this._disposable = Disposable.from(
this.disposable = Disposable.from(
window.onDidChangeTextEditorSelection(this.onTextEditorSelectionChanged, this)
);
}
@ -39,7 +39,7 @@ export abstract class AnnotationProviderBase extends Disposable {
async dispose() {
await this.clear();
this._disposable && this._disposable.dispose();
this.disposable && this.disposable.dispose();
}
private async onTextEditorSelectionChanged(e: TextEditorSelectionChangeEvent) {
@ -58,16 +58,32 @@ export abstract class AnnotationProviderBase extends Disposable {
return this.editor.document.uri;
}
protected decorationTypes: TextEditorDecorationType[] | undefined;
async clear() {
if (this.editor !== undefined) {
if (this.editor === undefined || this.decorationTypes === undefined || this.decorationTypes.length === 0) return;
if (this.decoration !== undefined) {
try {
if (this._highlightDecoration !== undefined) {
this.editor.setDecorations(this._highlightDecoration, []);
}
this.editor.setDecorations(this.decoration, []);
}
catch { }
}
if (this._decoration !== undefined) {
this.editor.setDecorations(this._decoration, []);
if (this.decorationTypes !== undefined && this.decorationTypes.length > 0) {
for (const dt of this.decorationTypes) {
try {
this.editor.setDecorations(dt, []);
}
catch { }
}
this.decorationTypes = undefined;
}
if (this.highlightDecoration !== undefined) {
try {
this.editor.setDecorations(this.highlightDecoration, []);
}
catch { }
}
@ -87,8 +103,8 @@ export abstract class AnnotationProviderBase extends Disposable {
if (changes !== undefined) {
await this.clear();
this._decoration = changes.decoration;
this._highlightDecoration = changes.highlightDecoration;
this.decoration = changes.decoration;
this.highlightDecoration = changes.highlightDecoration;
}
await this.provideAnnotation(this.editor === undefined ? undefined : this.editor.selection.active.line);
@ -103,8 +119,8 @@ export abstract class AnnotationProviderBase extends Disposable {
this.correlationKey = AnnotationProviderBase.getCorrelationKey(editor);
this.document = editor.document;
if (this._decorations !== undefined && this._decorations.length) {
this.editor.setDecorations(this._decoration!, this._decorations);
if (this.decorations !== undefined && this.decorations.length) {
this.editor.setDecorations(this.decoration!, this.decorations);
}
}

+ 1
- 1
src/annotations/annotations.ts View File

@ -89,7 +89,7 @@ export class Annotations {
showCommitDetailsCommand = `\`${commit.shortSha}\``;
}
const markdown = new MarkdownString(`${showCommitDetailsCommand} &nbsp; __${commit.author}__, ${commit.fromNow()} &nbsp; _(${commit.formatDate(dateFormat)})_ ${message}${commandBar}`);
const markdown = new MarkdownString(`${showCommitDetailsCommand} &nbsp; ![](${commit.getGravatarUri(Container.config.defaultGravatarsStyle).toString()}) &nbsp;__${commit.author}__, ${commit.fromNow()} &nbsp; _(${commit.formatDate(dateFormat)})_ ${message}${commandBar}`);
markdown.isTrusted = true;
return markdown;
}

+ 3
- 3
src/annotations/blameAnnotationProvider.ts View File

@ -49,7 +49,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
}
async selection(shaOrLine?: string | number, blame?: GitBlame) {
if (!this._highlightDecoration) return;
if (!this.highlightDecoration) return;
if (blame === undefined) {
blame = await this._blame;
@ -71,14 +71,14 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
}
if (!sha) {
this.editor.setDecorations(this._highlightDecoration, []);
this.editor.setDecorations(this.highlightDecoration, []);
return;
}
const highlightDecorationRanges = Arrays.filterMap(blame.lines,
l => l.sha === sha ? this.editor.document.validateRange(new Range(l.line, 0, l.line, RangeEndOfLineIndex)) : undefined);
this.editor.setDecorations(this._highlightDecoration, highlightDecorationRanges);
this.editor.setDecorations(this.highlightDecoration, highlightDecorationRanges);
}
async validate(): Promise<boolean> {

+ 50
- 12
src/annotations/gutterBlameAnnotationProvider.ts View File

@ -1,9 +1,10 @@
'use strict';
import { Strings } from '../system';
import { DecorationOptions, Range } from 'vscode';
import { Objects, Strings } from '../system';
import { DecorationOptions, DecorationRenderOptions, Range, TextEditorDecorationType, window } from 'vscode';
import { FileAnnotationType } from './annotationController';
import { Annotations } from './annotations';
import { BlameAnnotationProviderBase } from './blameAnnotationProvider';
import { GravatarDefaultStyle } from '../configuration';
import { GlyphChars } from '../constants';
import { Container } from '../container';
import { GitBlameCommit, ICommitFormatOptions } from '../gitService';
@ -34,11 +35,14 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
};
const now = Date.now();
const separateLines = Container.config.annotations.file.gutter.separateLines;
const gravatars = cfg.gravatars;
const gravatarDefault = Container.config.defaultGravatarsStyle;
const separateLines = cfg.separateLines;
const renderOptions = Annotations.gutterRenderOptions(separateLines, cfg.heatmap, cfg.format, options);
this._decorations = [];
this.decorations = [];
const decorationsMap: { [sha: string]: DecorationOptions | undefined } = Object.create(null);
const avatarDecorationsMap: { [email: string]: { decoration: TextEditorDecorationType, ranges: Range[] } } | undefined = gravatars ? Object.create(null) : undefined;
let commit: GitBlameCommit | undefined;
let compacted = false;
@ -70,7 +74,7 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
gutter.range = new Range(line, 0, line, 0);
this._decorations.push(gutter);
this.decorations.push(gutter);
continue;
}
@ -78,6 +82,9 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
compacted = false;
previousSha = l.sha;
commit = blame.commits.get(l.sha);
if (commit === undefined) continue;
gutter = decorationsMap[l.sha];
if (gutter !== undefined) {
gutter = {
@ -85,14 +92,15 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
range: new Range(line, 0, line, 0)
} as DecorationOptions;
this._decorations.push(gutter);
this.decorations.push(gutter);
if (gravatars && commit.email !== undefined) {
this.addOrUpdateGravatarDecoration(commit, gutter.range, gravatarDefault, avatarDecorationsMap!);
}
continue;
}
commit = blame.commits.get(l.sha);
if (commit === undefined) continue;
gutter = Annotations.gutter(commit, cfg.format, options, renderOptions);
if (cfg.heatmap.enabled) {
@ -101,12 +109,25 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
gutter.range = new Range(line, 0, line, 0);
this._decorations.push(gutter);
this.decorations.push(gutter);
if (gravatars && commit.email !== undefined) {
this.addOrUpdateGravatarDecoration(commit, gutter.range, gravatarDefault, avatarDecorationsMap!);
}
decorationsMap[l.sha] = gutter;
}
if (this._decorations.length) {
this.editor.setDecorations(this._decoration!, this._decorations);
if (this.decorations.length) {
this.editor.setDecorations(this.decoration!, this.decorations);
if (gravatars) {
this.decorationTypes = [];
for (const a of Objects.values(avatarDecorationsMap!)) {
this.decorationTypes.push(a.decoration);
this.editor.setDecorations(a.decoration, a.ranges);
}
}
}
const duration = process.hrtime(start);
@ -116,4 +137,21 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
this.selection(shaOrLine, blame);
return true;
}
addOrUpdateGravatarDecoration(commit: GitBlameCommit, range: Range, gravatarDefault: GravatarDefaultStyle, map: { [email: string]: { decoration: TextEditorDecorationType, ranges: Range[] } }) {
const avatarDecoration = map[commit.email!];
if (avatarDecoration !== undefined) {
avatarDecoration.ranges.push(range);
return;
}
map[commit.email!] = {
decoration: window.createTextEditorDecorationType({
gutterIconPath: commit.getGravatarUri(gravatarDefault),
gutterIconSize: '16px 16px'
} as DecorationRenderOptions),
ranges: [range]
};
}
}

+ 5
- 5
src/annotations/heatmapBlameAnnotationProvider.ts View File

@ -19,7 +19,7 @@ export class HeatmapBlameAnnotationProvider extends BlameAnnotationProviderBase
const now = Date.now();
const renderOptions = Annotations.heatmapRenderOptions();
this._decorations = [];
this.decorations = [];
const decorationsMap: { [sha: string]: DecorationOptions | undefined } = Object.create(null);
let commit: GitBlameCommit | undefined;
@ -35,7 +35,7 @@ export class HeatmapBlameAnnotationProvider extends BlameAnnotationProviderBase
range: new Range(line, 0, line, 0)
} as DecorationOptions;
this._decorations.push(heatmap);
this.decorations.push(heatmap);
continue;
}
@ -46,12 +46,12 @@ export class HeatmapBlameAnnotationProvider extends BlameAnnotationProviderBase
heatmap = Annotations.heatmap(commit, now, renderOptions);
heatmap.range = new Range(line, 0, line, 0);
this._decorations.push(heatmap);
this.decorations.push(heatmap);
decorationsMap[l.sha] = heatmap;
}
if (this._decorations.length) {
this.editor.setDecorations(this._decoration!, this._decorations);
if (this.decorations.length) {
this.editor.setDecorations(this.decoration!, this.decorations);
}
const duration = process.hrtime(start);

+ 5
- 5
src/annotations/hoverBlameAnnotationProvider.ts View File

@ -23,7 +23,7 @@ export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase {
const now = Date.now();
const renderOptions = Annotations.hoverRenderOptions(cfg.heatmap);
this._decorations = [];
this.decorations = [];
const decorationsMap: { [sha: string]: DecorationOptions } = Object.create(null);
let commit: GitBlameCommit | undefined;
@ -40,7 +40,7 @@ export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase {
range: new Range(line, 0, line, 0)
} as DecorationOptions;
this._decorations.push(hover);
this.decorations.push(hover);
continue;
}
@ -51,13 +51,13 @@ export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase {
hover = Annotations.hover(commit, renderOptions, now);
hover.range = new Range(line, 0, line, 0);
this._decorations.push(hover);
this.decorations.push(hover);
decorationsMap[l.sha] = hover;
}
if (this._decorations.length) {
this.editor.setDecorations(this._decoration!, this._decorations);
if (this.decorations.length) {
this.editor.setDecorations(this.decoration!, this.decorations);
}
const duration = process.hrtime(start);

+ 4
- 4
src/annotations/recentChangesAnnotationProvider.ts View File

@ -36,7 +36,7 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase {
const cfg = Container.config.annotations.file.recentChanges;
const dateFormat = Container.config.defaultDateFormat;
this._decorations = [];
this.decorations = [];
for (const chunk of diff.chunks) {
let count = chunk.currentPosition.start - 2;
@ -50,7 +50,7 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase {
const range = this.editor.document.validateRange(new Range(new Position(count, 0), new Position(count, RangeEndOfLineIndex)));
if (cfg.hover.details) {
this._decorations.push({
this.decorations.push({
hoverMessage: Annotations.getHoverMessage(commit, dateFormat, await Container.git.hasRemote(commit.repoPath), Container.config.blame.file.annotationType),
range: range
} as DecorationOptions);
@ -61,14 +61,14 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase {
message = Annotations.getHoverDiffMessage(commit, this._uri, line);
}
this._decorations.push({
this.decorations.push({
hoverMessage: message,
range: range
} as DecorationOptions);
}
}
this.editor.setDecorations(this._highlightDecoration!, this._decorations);
this.editor.setDecorations(this.highlightDecoration!, this.decorations);
const duration = process.hrtime(start);
Logger.log(`${(duration[0] * 1000) + Math.floor(duration[1] / 1000000)} ms to compute recent changes annotations`);

+ 8
- 2
src/configuration.ts View File

@ -7,6 +7,7 @@ import { LineAnnotationType } from './currentLineController';
import { GitExplorerView } from './views/gitExplorer';
import { OutputLevel } from './logger';
import { Container } from './container';
import { clearGravatarCache } from './gitService';
export { ExtensionKey };
@ -50,7 +51,7 @@ export enum ExplorerFilesLayout {
Tree = 'tree'
}
export enum GravatarDefault {
export enum GravatarDefaultStyle {
Faces = 'wavatar',
Geometric = 'identicon',
Monster = 'monsterid',
@ -166,7 +167,6 @@ export interface IExplorerConfig {
commitFileFormat: string;
// dateFormat: string | null;
gravatars: boolean;
gravatarsDefault: GravatarDefault;
showTrackingBranch: boolean;
stashFormat: string;
stashFileFormat: string;
@ -210,6 +210,7 @@ export interface IConfig {
format: string;
dateFormat: string | null;
compact: boolean;
gravatars: boolean;
heatmap: {
enabled: boolean;
location: 'left' | 'right';
@ -285,6 +286,7 @@ export interface IConfig {
defaultDateFormat: string | null;
defaultDateStyle: DateStyle;
defaultGravatarsStyle: GravatarDefaultStyle;
gitExplorer: IGitExplorerConfig;
@ -342,6 +344,10 @@ export class Configuration {
Container.resetConfig();
if (configuration.changed(e, configuration.name('defaultGravatarsStyle').value)) {
clearGravatarCache();
}
const section = configuration.name('keymap').value;
if (configuration.changed(e, section)) {
setCommandContext(CommandContext.KeyMap, this.get<KeyMap>(section));

+ 15
- 2
src/extension.ts View File

@ -141,11 +141,24 @@ async function migrateSettings(context: ExtensionContext, previousVersion: strin
if (inspection.globalValue !== undefined) {
await configuration.update(section, inspection.globalValue, ConfigurationTarget.Global);
await configuration.update(oldSection, undefined, ConfigurationTarget.Global);
}
else if (inspection.workspaceFolderValue !== undefined) {
await configuration.update(section, inspection.workspaceFolderValue, ConfigurationTarget.WorkspaceFolder);
await configuration.update(oldSection, undefined, ConfigurationTarget.WorkspaceFolder);
}
}
}
if (Versions.compare(previous, Versions.from(7, 3, 0, 'beta4')) !== 1) {
const oldSection = 'gitExplorer.gravatarsDefault';
const inspection = configuration.inspect(oldSection);
if (inspection !== undefined) {
const section = configuration.name('defaultGravatarsStyle').value;
if (inspection.globalValue !== undefined) {
await configuration.update(section, inspection.globalValue, ConfigurationTarget.Global);
}
else if (inspection.workspaceFolderValue !== undefined) {
await configuration.update(section, inspection.workspaceFolderValue, ConfigurationTarget.WorkspaceFolder);
}
}
}

+ 4
- 4
src/git/models/commit.ts View File

@ -1,7 +1,7 @@
'use strict';
import { Dates, Strings } from '../../system';
import { Uri } from 'vscode';
import { configuration, DateStyle, GravatarDefault } from '../../configuration';
import { configuration, DateStyle, GravatarDefaultStyle } from '../../configuration';
import { GlyphChars } from '../../constants';
import { Container } from '../../container';
import { Git } from '../git';
@ -171,15 +171,15 @@ export abstract class GitCommit {
return GitUri.getFormattedPath(this.fileName, separator);
}
getGravatarUri(fallback: GravatarDefault): Uri {
getGravatarUri(fallback: GravatarDefaultStyle, size: number = 16): Uri {
const key = this.email
? `${ this.email.trim().toLowerCase() }`
? `${this.email.trim().toLowerCase() class="si">}:${size}`
: '';
let gravatar = gravatarCache.get(key);
if (gravatar !== undefined) return gravatar;
gravatar = Uri.parse(`https://www.gravatar.com/avatar/${this.email ? Strings.md5(this.email, 'hex') : '00000000000000000000000000000000'}.jpg?s=22&d=${fallback}`);
gravatar = Uri.parse(`https://www.gravatar.com/avatar/${this.email ? Strings.md5(this.email, 'hex') : '00000000000000000000000000000000'}.jpg?s=${size}&d=${fallback}`);
// HACK: Monkey patch Uri.toString to avoid the unwanted query string encoding
const originalToStringFn = gravatar.toString;

+ 1
- 2
src/views/commitFileNode.ts View File

@ -1,7 +1,6 @@
'use strict';
import { Command, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
import { GravatarDefault } from '../configuration';
import { Container } from '../container';
import { Explorer, ExplorerNode, ResourceType } from './explorerNode';
import { CommitFormatter, getGitStatusIcon, GitLogCommit, GitUri, ICommitFormatOptions, IGitStatusFile, IStatusFormatOptions, StatusFileFormatter } from '../gitService';
@ -69,7 +68,7 @@ export class CommitFileNode extends ExplorerNode {
};
}
else if ((this.displayAs & CommitFileNodeDisplayAs.Gravatar) === CommitFileNodeDisplayAs.Gravatar) {
item.iconPath = this.commit.getGravatarUri(this.explorer.config.gravatarsDefault || GravatarDefault.Robot);
item.iconPath = this.commit.getGravatarUri(Container.config.defaultGravatarsStyle);
}
item.command = this.getCommand();

+ 2
- 2
src/views/commitNode.ts View File

@ -3,7 +3,7 @@ import { Arrays, Iterables, Strings } from '../system';
import { Command, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
import { CommitFileNode, CommitFileNodeDisplayAs } from './commitFileNode';
import { ExplorerFilesLayout, GravatarDefault } from '../configuration';
import { ExplorerFilesLayout } from '../configuration';
import { Container } from '../container';
import { FolderNode, IFileExplorerNode } from './folderNode';
import { Explorer, ExplorerNode, ExplorerRefNode, ResourceType } from './explorerNode';
@ -54,7 +54,7 @@ export class CommitNode extends ExplorerRefNode {
: ResourceType.Commit;
if (this.explorer.config.gravatars) {
item.iconPath = this.commit.getGravatarUri(this.explorer.config.gravatarsDefault || GravatarDefault.Robot);
item.iconPath = this.commit.getGravatarUri(Container.config.defaultGravatarsStyle);
} else {
item.iconPath = {
dark: Container.context.asAbsolutePath('images/dark/icon-commit.svg'),

+ 3
- 7
src/views/gitExplorer.ts View File

@ -7,7 +7,7 @@ import { CommandContext, GlyphChars, setCommandContext, WorkspaceState } from '.
import { Container } from '../container';
import { RefreshNodeCommandArgs } from './explorerCommands';
import { ExplorerNode, HistoryNode, MessageNode, RefreshReason, RepositoriesNode, RepositoryNode } from './explorerNodes';
import { clearGravatarCache, GitUri } from '../gitService';
import { GitUri } from '../gitService';
import { Logger } from '../logger';
export * from './explorerNodes';
@ -70,13 +70,9 @@ export class GitExplorer implements TreeDataProvider {
private async onConfigurationChanged(e: ConfigurationChangeEvent) {
const initializing = configuration.initializing(e);
if (!initializing && !configuration.changed(e, configuration.name('gitExplorer').value)) return;
if (!initializing &&
(configuration.changed(e, configuration.name('gitExplorer')('gravatars').value) ||
configuration.changed(e, configuration.name('gitExplorer')('gravatarsDefault').value))) {
clearGravatarCache();
}
!configuration.changed(e, configuration.name('gitExplorer').value) &&
!configuration.changed(e, configuration.name('defaultGravatarsStyle').value)) return;
if (initializing || configuration.changed(e, configuration.name('gitExplorer')('autoRefresh').value)) {
this.setAutoRefresh(configuration.get<boolean>(configuration.name('gitExplorer')('autoRefresh').value));

+ 3
- 7
src/views/resultsExplorer.ts View File

@ -6,7 +6,7 @@ import { CommandContext, setCommandContext, WorkspaceState } from '../constants'
import { Container } from '../container';
import { RefreshNodeCommandArgs } from './explorerCommands';
import { CommitResultsNode, CommitsResultsNode, ComparisionResultsNode, ExplorerNode, MessageNode, RefreshReason, ResourceType } from './explorerNodes';
import { clearGravatarCache, GitLog, GitLogCommit } from '../gitService';
import { GitLog, GitLogCommit } from '../gitService';
import { Logger } from '../logger';
import { Messages } from '../messages';
@ -44,13 +44,9 @@ export class ResultsExplorer implements TreeDataProvider {
private async onConfigurationChanged(e: ConfigurationChangeEvent) {
const initializing = configuration.initializing(e);
if (!initializing && !configuration.changed(e, configuration.name('resultsExplorer').value)) return;
if (!initializing &&
(configuration.changed(e, configuration.name('resultsExplorer')('gravatars').value) ||
configuration.changed(e, configuration.name('resultsExplorer')('gravatarsDefault').value))) {
clearGravatarCache();
}
!configuration.changed(e, configuration.name('resultsExplorer').value) &&
!configuration.changed(e, configuration.name('defaultGravatarsStyle').value)) return;
if (!initializing && this._roots.length !== 0) {
this.refresh(RefreshReason.ConfigurationChanged);

Loading…
Cancel
Save