瀏覽代碼

Fixes #729 - broken show more in search & compare

Adds a Show All command to the Show More nodes
Improves experience after starting a new search or compare
Fixes issues with maxCount == 0
main
Eric Amodio 5 年之前
父節點
當前提交
665985330c
共有 17 個檔案被更改,包括 207 行新增56 行删除
  1. +4
    -0
      images/dark/icon-ellipsis.svg
  2. +4
    -0
      images/light/icon-ellipsis.svg
  3. +23
    -0
      package.json
  4. +1
    -1
      src/views/nodes/branchNode.ts
  5. +1
    -1
      src/views/nodes/branchTrackingStatusNode.ts
  6. +3
    -1
      src/views/nodes/branchesNode.ts
  7. +7
    -3
      src/views/nodes/common.ts
  8. +33
    -12
      src/views/nodes/compareResultsNode.ts
  9. +1
    -1
      src/views/nodes/contributorNode.ts
  10. +3
    -1
      src/views/nodes/lineHistoryTrackerNode.ts
  11. +49
    -10
      src/views/nodes/resultsCommitsNode.ts
  12. +39
    -8
      src/views/nodes/resultsFilesNode.ts
  13. +7
    -6
      src/views/nodes/searchResultsCommitsNode.ts
  14. +1
    -1
      src/views/nodes/tagNode.ts
  15. +18
    -9
      src/views/nodes/viewNode.ts
  16. +11
    -2
      src/views/searchView.ts
  17. +2
    -0
      src/views/viewCommands.ts

+ 4
- 0
images/dark/icon-ellipsis.svg 查看文件

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 22">
<path fill="#C5C5C5" d="M3.523 10C2.684 10 2 10.684 2 11.523c0 .839.684 1.522 1.523 1.522.839 0 1.522-.683 1.522-1.522S4.362 10 3.523 10zM8 10c-.839 0-1.523.684-1.523 1.523 0 .839.684 1.522 1.523 1.522.839 0 1.523-.683 1.523-1.522S8.839 10 8 10zm4.477 0c-.839 0-1.522.684-1.522 1.523 0 .839.683 1.522 1.522 1.522.84 0 1.523-.683 1.523-1.522S13.316 10 12.477 10z"/>
</svg>

+ 4
- 0
images/light/icon-ellipsis.svg 查看文件

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 22">
<path fill="#424242" d="M3.523 10C2.684 10 2 10.684 2 11.523c0 .839.684 1.522 1.523 1.522.839 0 1.522-.683 1.522-1.522S4.362 10 3.523 10zM8 10c-.839 0-1.523.684-1.523 1.523 0 .839.684 1.522 1.523 1.522.839 0 1.523-.683 1.523-1.522S8.839 10 8 10zm4.477 0c-.839 0-1.522.684-1.522 1.523 0 .839.683 1.522 1.522 1.522.84 0 1.523-.683 1.523-1.522S13.316 10 12.477 10z"/>
</svg>

+ 23
- 0
package.json 查看文件

@ -2959,6 +2959,15 @@
"dark": "images/dark/icon-refresh.svg",
"light": "images/light/icon-refresh.svg"
}
},
{
"command": "gitlens.views.showAllChildren",
"title": "Show All",
"category": "GitLens",
"icon": {
"dark": "images/dark/icon-unfold.svg",
"light": "images/light/icon-unfold.svg"
}
}
],
"menus": {
@ -3618,6 +3627,10 @@
{
"command": "gitlens.views.refreshNode",
"when": "false"
},
{
"command": "gitlens.views.showAllChildren",
"when": "false"
}
],
"editor/context": [
@ -4806,6 +4819,16 @@
"command": "gitlens.views.refreshNode",
"when": "viewItem =~ /gitlens:(?!file\\b)/",
"group": "9_gitlens@1"
},
{
"command": "gitlens.views.showAllChildren",
"when": "viewItem =~ /gitlens:pager\\b/",
"group": "inline@1"
},
{
"command": "gitlens.views.showAllChildren",
"when": "viewItem =~ /gitlens:pager\\b/",
"group": "1_gitlens@1"
}
]
},

+ 1
- 1
src/views/nodes/branchNode.ts 查看文件

@ -79,7 +79,7 @@ export class BranchNode extends ViewRefNode implements Pageabl
}
const log = await Container.git.getLog(this.uri.repoPath!, {
maxCount: this.maxCount || this.view.config.defaultItemLimit,
maxCount: this.maxCount !== undefined ? this.maxCount : this.view.config.defaultItemLimit,
ref: this.ref
});
if (log === undefined) return [new MessageNode(this.view, this, 'No commits could be found.')];

+ 1
- 1
src/views/nodes/branchTrackingStatusNode.ts 查看文件

@ -44,7 +44,7 @@ export class BranchTrackingStatusNode extends ViewNode implements
: `${this.status.ref}..${this.status.upstream}`;
const log = await Container.git.getLog(this.uri.repoPath!, {
maxCount: this.maxCount || this.view.config.defaultItemLimit,
maxCount: this.maxCount !== undefined ? this.maxCount : this.view.config.defaultItemLimit,
ref: range
});
if (log === undefined) return [];

+ 3
- 1
src/views/nodes/branchesNode.ts 查看文件

@ -3,7 +3,7 @@ import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { ViewBranchesLayout } from '../../configuration';
import { Container } from '../../container';
import { GitUri, Repository } from '../../git/gitService';
import { Arrays, Iterables } from '../../system';
import { Arrays, debug, gate, Iterables } from '../../system';
import { RepositoriesView } from '../repositoriesView';
import { BranchNode } from './branchNode';
import { BranchOrTagFolderNode } from './branchOrTagFolderNode';
@ -78,6 +78,8 @@ export class BranchesNode extends ViewNode {
return item;
}
@gate()
@debug()
refresh() {
this._children = undefined;
}

+ 7
- 3
src/views/nodes/common.ts 查看文件

@ -152,6 +152,10 @@ export abstract class PagerNode extends ViewNode {
this._args.previousNode = previousNode;
}
showAll() {
this.view.refreshNode(this.parent!, true, { ...this._args, maxCount: 0 });
}
getChildren(): ViewNode[] | Promise<ViewNode[]> {
return [];
}
@ -161,8 +165,8 @@ export abstract class PagerNode extends ViewNode {
item.contextValue = ResourceType.Pager;
item.command = this.getCommand();
item.iconPath = {
dark: Container.context.asAbsolutePath('images/dark/icon-unfold.svg'),
light: Container.context.asAbsolutePath('images/light/icon-unfold.svg')
dark: Container.context.asAbsolutePath('images/dark/icon-ellipsis.svg'),
light: Container.context.asAbsolutePath('images/light/icon-ellipsis.svg')
};
return item;
}
@ -171,7 +175,7 @@ export abstract class PagerNode extends ViewNode {
return {
title: 'Refresh',
command: 'gitlens.views.refreshNode',
arguments: [this.parent, false, this._args]
arguments: [this.parent, true, this._args]
};
}
}

+ 33
- 12
src/views/nodes/compareResultsNode.ts 查看文件

@ -3,13 +3,15 @@ import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { NamedRef } from '../../constants';
import { Container } from '../../container';
import { GitService, GitUri } from '../../git/gitService';
import { log, Strings } from '../../system';
import { debug, gate, log, Strings } from '../../system';
import { CompareView } from '../compareView';
import { CommitsQueryResults, ResultsCommitsNode } from './resultsCommitsNode';
import { ResultsFilesNode } from './resultsFilesNode';
import { ResourceType, SubscribeableViewNode, ViewNode } from './viewNode';
export class CompareResultsNode extends SubscribeableViewNode<CompareView> {
private _children: ViewNode[] | undefined;
constructor(
view: CompareView,
public readonly repoPath: string,
@ -39,10 +41,21 @@ export class CompareResultsNode extends SubscribeableViewNode {
}
getChildren(): ViewNode[] {
return [
new ResultsCommitsNode(this.view, this, this.uri.repoPath!, this.getCommitsQuery.bind(this)),
new ResultsFilesNode(this.view, this, this.uri.repoPath!, this._ref1.ref, this._ref2.ref)
];
if (this._children === undefined) {
this._children = [
new ResultsCommitsNode(
this.view,
this,
this.uri.repoPath!,
'? commits',
this.getCommitsQuery.bind(this),
true,
false
),
new ResultsFilesNode(this.view, this, this.uri.repoPath!, this._ref1.ref, this._ref2.ref)
];
}
return this._children;
}
async getTreeItem(): Promise<TreeItem> {
@ -86,14 +99,12 @@ export class CompareResultsNode extends SubscribeableViewNode {
void this.triggerChange();
}
@log()
async unpin() {
if (!this._pinned) return;
await this.view.updatePinnedComparison(this.getPinnableId());
@gate()
@debug()
refresh(reset: boolean = false) {
if (!reset) return;
this._pinned = false;
void this.triggerChange();
this._children = undefined;
}
@log()
@ -118,6 +129,16 @@ export class CompareResultsNode extends SubscribeableViewNode {
this.view.triggerNodeChange(this);
}
@log()
async unpin() {
if (!this._pinned) return;
await this.view.updatePinnedComparison(this.getPinnableId());
this._pinned = false;
void this.triggerChange();
}
protected subscribe() {
return undefined;
}

+ 1
- 1
src/views/nodes/contributorNode.ts 查看文件

@ -26,7 +26,7 @@ export class ContributorNode extends ViewNode implements Pagea
async getChildren(): Promise<ViewNode[]> {
const log = await Container.git.getLog(this.uri.repoPath!, {
maxCount: this.maxCount || this.view.config.defaultItemLimit,
maxCount: this.maxCount !== undefined ? this.maxCount : this.view.config.defaultItemLimit,
authors: [this.contributor.name]
});
if (log === undefined) return [new MessageNode(this.view, this, 'No commits could be found.')];

+ 3
- 1
src/views/nodes/lineHistoryTrackerNode.ts 查看文件

@ -90,7 +90,9 @@ export class LineHistoryTrackerNode extends SubscribeableViewNode
}
@gate()
@debug()
@debug({
exit: r => `returned ${r}`
})
async refresh(reset: boolean = false) {
const cc = Logger.getCorrelationContext();

+ 49
- 10
src/views/nodes/resultsCommitsNode.ts 查看文件

@ -2,12 +2,12 @@
import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { Container } from '../../container';
import { GitLog, GitUri } from '../../git/gitService';
import { Iterables } from '../../system';
import { debug, gate, Iterables } from '../../system';
import { ViewWithFiles } from '../viewBase';
import { CommitNode } from './commitNode';
import { ShowMoreNode } from './common';
import { getBranchesAndTagTipsFn, insertDateMarkers } from './helpers';
import { PageableViewNode, ResourceType, ViewNode } from './viewNode';
import { getNextId, PageableViewNode, ResourceType, ViewNode } from './viewNode';
export interface CommitsQueryResults {
label: string;
@ -18,15 +18,25 @@ export class ResultsCommitsNode extends ViewNode implements Pagea
readonly supportsPaging: boolean = true;
maxCount: number | undefined;
// Generate a unique id so the node order is preserved, since we update the label when the query completes
private readonly _uniqueId: number = getNextId('ResultsCommitsNode');
constructor(
view: ViewWithFiles,
parent: ViewNode,
public readonly repoPath: string,
private readonly _commitsQuery: (maxCount: number | undefined) => Promise<CommitsQueryResults>
private _label: string,
private readonly _commitsQuery: (maxCount: number | undefined) => Promise<CommitsQueryResults>,
private _querying = true,
private readonly _expand = true
) {
super(GitUri.fromRepoPath(repoPath), view, parent);
}
get id(): string {
return `${this._uniqueId}|${this._instanceId}:${this.type}(${this.repoPath})`;
}
get type(): ResourceType {
return ResourceType.ResultsCommits;
}
@ -47,14 +57,41 @@ export class ResultsCommitsNode extends ViewNode implements Pagea
];
if (log.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Results', children[children.length - 1]));
children.push(new ShowMoreNode(this.view, this, 'Results', children[children.length - 1], this.maxCount));
}
return children;
}
async getTreeItem(): Promise<TreeItem> {
const { label, log } = await this.getCommitsQueryResults();
let state;
let label;
let log;
if (this._querying) {
// Need to use Collapsed before we have results or the item won't show up in the view until the children are awaited
state = TreeItemCollapsibleState.Collapsed;
label = this._label;
this.getCommitsQueryResults().then(({ log }) => {
this._querying = false;
if (log != null) {
this.maxCount = log.maxCount;
}
this.triggerChange(false);
});
}
else {
({ label, log } = await this.getCommitsQueryResults());
if (log != null) {
this.maxCount = log.maxCount;
}
state = this._expand ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.Collapsed;
if (log == null || log.count === 0) {
state = TreeItemCollapsibleState.None;
}
}
let description;
if ((await Container.git.getRepositoryCount()) > 1) {
@ -62,17 +99,19 @@ export class ResultsCommitsNode extends ViewNode implements Pagea
description = (repo && repo.formattedName) || this.repoPath;
}
const item = new TreeItem(
label,
log && log.count > 0 ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None
);
const item = new TreeItem(label, state);
item.contextValue = this.type;
item.description = description;
item.id = this.id;
return item;
}
refresh() {
@gate()
@debug()
refresh(reset: boolean = false) {
if (!reset) return;
this._commitsQueryResults = this._commitsQuery(this.maxCount);
}

+ 39
- 8
src/views/nodes/resultsFilesNode.ts 查看文件

@ -4,11 +4,11 @@ import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { ViewFilesLayout } from '../../configuration';
import { Container } from '../../container';
import { GitFile, GitUri } from '../../git/gitService';
import { Arrays, Iterables, Strings } from '../../system';
import { Arrays, debug, gate, Iterables, Strings } from '../../system';
import { ViewWithFiles } from '../viewBase';
import { FileNode, FolderNode } from './folderNode';
import { ResultsFileNode } from './resultsFileNode';
import { ResourceType, ViewNode } from './viewNode';
import { getNextId, ResourceType, ViewNode } from './viewNode';
export interface FilesQueryResults {
label: string;
@ -16,6 +16,9 @@ export interface FilesQueryResults {
}
export class ResultsFilesNode extends ViewNode<ViewWithFiles> {
// Generate a unique id so the node order is preserved, since we update the label when the query completes
private readonly _uniqueId: number = getNextId('ResultsFilesNode');
constructor(
view: ViewWithFiles,
parent: ViewNode,
@ -26,6 +29,10 @@ export class ResultsFilesNode extends ViewNode {
super(GitUri.fromRepoPath(repoPath), view, parent);
}
get id(): string {
return `${this._uniqueId}|${this._instanceId}:gitlens:results:files(${this.repoPath})`;
}
async getChildren(): Promise<ViewNode[]> {
const { diff } = await this.getFilesQueryResults();
if (diff === undefined) return [];
@ -57,21 +64,45 @@ export class ResultsFilesNode extends ViewNode {
}
async getTreeItem(): Promise<TreeItem> {
const { diff, label } = await this.getFilesQueryResults();
let state;
let label;
let diff;
if (this._querying) {
// Need to use Collapsed before we have results or the item won't show up in the view until the children are awaited
state = TreeItemCollapsibleState.Collapsed;
label = '? files changed';
this.getFilesQueryResults().then(_ => {
this._querying = false;
this.triggerChange(false);
});
}
else {
({ label, diff } = await this.getFilesQueryResults());
state = TreeItemCollapsibleState.Expanded;
if (diff == null || diff.length === 0) {
state = TreeItemCollapsibleState.None;
}
}
const item = new TreeItem(
label,
diff && diff.length > 0 ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None
);
const item = new TreeItem(label, state);
item.contextValue = ResourceType.ResultsFiles;
item.id = this.id;
return item;
}
refresh() {
@gate()
@debug()
refresh(reset: boolean = false) {
if (!reset) return;
this._filesQueryResults = this.getFilesQueryResultsCore();
}
private _filesQueryResults: Promise<FilesQueryResults> | undefined;
private _querying = true;
private getFilesQueryResults() {
if (this._filesQueryResults === undefined) {

+ 7
- 6
src/views/nodes/searchResultsCommitsNode.ts 查看文件

@ -1,5 +1,5 @@
'use strict';
import { TreeItem } from 'vscode';
import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { SearchCommitsCommandArgs } from '../../commands';
import { Commands } from '../../commands/common';
import { GitRepoSearchBy } from '../../git/gitService';
@ -14,9 +14,11 @@ export class SearchResultsCommitsNode extends ResultsCommitsNode {
repoPath: string,
public readonly search: string,
public readonly searchBy: GitRepoSearchBy,
commitsQuery: (maxCount: number | undefined) => Promise<CommitsQueryResults>
label: string,
commitsQuery: (maxCount: number | undefined) => Promise<CommitsQueryResults>,
_querying = true
) {
super(view, parent, repoPath, commitsQuery);
super(view, parent, repoPath, label, commitsQuery, _querying, true);
}
get type(): ResourceType {
@ -24,11 +26,9 @@ export class SearchResultsCommitsNode extends ResultsCommitsNode {
}
async getTreeItem(): Promise<TreeItem> {
const { log } = await super.getCommitsQueryResults();
const item = await super.getTreeItem();
if (log == null || log.count === 0) {
if (item.collapsibleState === TreeItemCollapsibleState.None) {
const args: SearchCommitsCommandArgs = {
search: this.search,
searchBy: this.searchBy,
@ -40,6 +40,7 @@ export class SearchResultsCommitsNode extends ResultsCommitsNode {
arguments: [args]
};
}
item.id = undefined;
return item;
}

+ 1
- 1
src/views/nodes/tagNode.ts 查看文件

@ -32,7 +32,7 @@ export class TagNode extends ViewRefNode implements PageableVi
async getChildren(): Promise<ViewNode[]> {
const log = await Container.git.getLog(this.uri.repoPath!, {
maxCount: this.maxCount || this.view.config.defaultItemLimit,
maxCount: this.maxCount !== undefined ? this.maxCount : this.view.config.defaultItemLimit,
ref: this.tag.name
});
if (log === undefined) return [new MessageNode(this.view, this, 'No commits could be found.')];

+ 18
- 9
src/views/nodes/viewNode.ts 查看文件

@ -53,12 +53,21 @@ export interface ViewNode {
readonly id?: string;
}
const counter = 0;
function getViewNodeInstanceId() {
// if (counter === Number.MAX_SAFE_INTEGER) {
// counter = 0;
// }
// counter++;
const counters: { [key: string]: number } = {
instanceId: 0
};
export function getNextId(key?: string) {
if (key === undefined) {
key = 'instanceId';
}
let counter = counters[key] || 0;
if (counter === Number.MAX_SAFE_INTEGER) {
counter = 0;
}
counter++;
counters[key] = counter;
return counter;
}
@ -67,7 +76,7 @@ export abstract class ViewNode {
protected readonly _instanceId: number;
constructor(uri: GitUri, public readonly view: TView, protected readonly parent?: ViewNode) {
this._instanceId = getViewNodeInstanceId();
this._instanceId = 0; //getNextId();
this._uri = uri;
if (Logger.isDebugging) {
@ -110,8 +119,8 @@ export abstract class ViewNode {
@gate()
@debug()
triggerChange(): Promise<void> {
return this.view.refreshNode(this);
triggerChange(reset: boolean = false): Promise<void> {
return this.view.refreshNode(this, reset);
}
}

+ 11
- 2
src/views/searchView.ts 查看文件

@ -118,7 +118,16 @@ export class SearchView extends ViewBase {
);
return this.addResults(
new SearchResultsCommitsNode(this, this._root!, repoPath, search, searchBy, searchQueryFn)
new SearchResultsCommitsNode(
this,
this._root!,
repoPath,
search,
searchBy,
`Searching for ${typeof options.label === 'string' ? options.label : options.label.label}`,
searchQueryFn,
true
)
);
}
@ -143,7 +152,7 @@ export class SearchView extends ViewBase {
});
return this.addResults(
new SearchResultsCommitsNode(this, this._root!, repoPath, search, searchBy, searchQueryFn)
new SearchResultsCommitsNode(this, this._root!, repoPath, search, searchBy, label, searchQueryFn, false)
);
}

+ 2
- 0
src/views/viewCommands.ts 查看文件

@ -39,6 +39,7 @@ import {
viewSupportsNodeDismissal
} from './nodes';
import { Strings } from '../system/string';
import { PagerNode } from './nodes/common';
export interface RefreshNodeCommandArgs {
maxCount?: number;
@ -73,6 +74,7 @@ export class ViewCommands implements Disposable {
(node: ViewNode) => viewSupportsNodeDismissal(node.view) && node.view.dismissNode(node),
this
);
commands.registerCommand('gitlens.views.showAllChildren', (node: PagerNode) => node.showAll(), this);
commands.registerCommand('gitlens.views.fetch', this.fetch, this);
commands.registerCommand('gitlens.views.pull', this.pull, this);

Loading…
取消
儲存