Browse Source

Persists show more during changes

Fixes show more in file/line history
main
Eric Amodio 5 years ago
parent
commit
a402de3c51
14 changed files with 173 additions and 90 deletions
  1. +13
    -0
      package.json
  2. +7
    -4
      src/views/nodes/branchNode.ts
  3. +4
    -3
      src/views/nodes/branchTrackingStatusNode.ts
  4. +29
    -16
      src/views/nodes/common.ts
  5. +4
    -3
      src/views/nodes/contributorNode.ts
  6. +4
    -2
      src/views/nodes/fileHistoryNode.ts
  7. +4
    -2
      src/views/nodes/lineHistoryNode.ts
  8. +6
    -3
      src/views/nodes/reflogNode.ts
  9. +4
    -3
      src/views/nodes/reflogRecordNode.ts
  10. +6
    -6
      src/views/nodes/resultsCommitsNode.ts
  11. +4
    -3
      src/views/nodes/tagNode.ts
  12. +23
    -18
      src/views/nodes/viewNode.ts
  13. +55
    -20
      src/views/viewBase.ts
  14. +10
    -7
      src/views/viewCommands.ts

+ 13
- 0
package.json View File

@ -2979,6 +2979,15 @@
}
},
{
"command": "gitlens.views.showMoreChildren",
"title": "Show More",
"category": "GitLens",
"icon": {
"dark": "images/dark/icon-unfold.svg",
"light": "images/light/icon-unfold.svg"
}
},
{
"command": "gitlens.views.showAllChildren",
"title": "Show All",
"category": "GitLens",
@ -3647,6 +3656,10 @@
"when": "false"
},
{
"command": "gitlens.views.showMoreChildren",
"when": "false"
},
{
"command": "gitlens.views.showAllChildren",
"when": "false"
}

+ 7
- 4
src/views/nodes/branchNode.ts View File

@ -13,8 +13,9 @@ import { getBranchesAndTagTipsFn, insertDateMarkers } from './helpers';
import { PageableViewNode, ResourceType, ViewNode, ViewRefNode } from './viewNode';
export class BranchNode extends ViewRefNode<RepositoriesView> implements PageableViewNode {
readonly supportsPaging: boolean = true;
maxCount: number | undefined;
readonly supportsPaging = true;
readonly rememberLastMaxCount = true;
maxCount: number | undefined = this.view.getNodeLastMaxCount(this);
private _children: ViewNode[] | undefined;
@ -94,7 +95,9 @@ export class BranchNode extends ViewRefNode implements Pageabl
);
if (log.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Commits', children[children.length - 1]));
children.push(
new ShowMoreNode(this.view, this, 'Commits', log.maxCount, children[children.length - 1])
);
}
this._children = children;
@ -204,7 +207,7 @@ export class BranchNode extends ViewRefNode implements Pageabl
@gate()
@debug()
refresh(reset: boolean = false) {
refresh() {
this._children = undefined;
}
}

+ 4
- 3
src/views/nodes/branchTrackingStatusNode.ts View File

@ -17,8 +17,9 @@ export interface BranchTrackingStatus {
}
export class BranchTrackingStatusNode extends ViewNode<ViewWithFiles> implements PageableViewNode {
readonly supportsPaging: boolean = true;
maxCount: number | undefined;
readonly supportsPaging = true;
readonly rememberLastMaxCount = true;
maxCount: number | undefined = this.view.getNodeLastMaxCount(this);
constructor(
view: ViewWithFiles,
@ -74,7 +75,7 @@ export class BranchTrackingStatusNode extends ViewNode implements
}
if (log.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Commits', children[children.length - 1]));
children.push(new ShowMoreNode(this.view, this, 'Commits', log.maxCount, children[children.length - 1]));
}
return children;
}

+ 29
- 16
src/views/nodes/common.ts View File

@ -2,8 +2,7 @@ import { Command, ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri } from 'vsc
import { GlyphChars } from '../../constants';
import { Container } from '../../container';
import { View } from '../viewBase';
import { RefreshNodeCommandArgs } from '../viewCommands';
import { ResourceType, unknownGitUri, ViewNode } from './viewNode';
import { PageableViewNode, ResourceType, unknownGitUri, ViewNode } from './viewNode';
export class MessageNode extends ViewNode {
constructor(
@ -137,23 +136,29 @@ export class UpdateableMessageNode extends ViewNode {
}
export abstract class PagerNode extends ViewNode {
protected _args: RefreshNodeCommandArgs = {};
constructor(
view: View,
parent: ViewNode,
parent: ViewNode & PageableViewNode,
protected readonly message: string,
previousNode?: ViewNode,
maxCount: number = Container.config.views.pageItemLimit
maxCount: number | undefined,
private readonly _previousNode?: ViewNode,
private readonly _pageSize: number = Container.config.views.pageItemLimit
) {
super(unknownGitUri, view, parent);
this._args.maxCount = maxCount;
this._args.previousNode = previousNode;
parent.maxCount = maxCount;
}
showMore() {
return this.view.showMoreNodeChildren(
this.parent! as ViewNode & PageableViewNode,
this._pageSize,
this._previousNode
);
}
showAll() {
this.view.refreshNode(this.parent!, true, { ...this._args, maxCount: 0 });
return this.view.showMoreNodeChildren(this.parent! as ViewNode & PageableViewNode, 0, this._previousNode);
}
getChildren(): ViewNode[] | Promise<ViewNode[]> {
@ -173,23 +178,31 @@ export abstract class PagerNode extends ViewNode {
getCommand(): Command | undefined {
return {
title: 'Refresh',
command: 'gitlens.views.refreshNode',
arguments: [this.parent, true, this._args]
title: 'Show More',
command: 'gitlens.views.showMoreChildren',
arguments: [this]
};
}
}
export class ShowMoreNode extends PagerNode {
constructor(view: View, parent: ViewNode, itemType: string, previousNode: ViewNode, maxCount?: number) {
constructor(
view: View,
parent: ViewNode & PageableViewNode,
itemType: string,
maxCount: number | undefined,
previousNode: ViewNode,
pageSize?: number
) {
super(
view,
parent,
maxCount === 0
pageSize === 0
? `Show All ${itemType} ${GlyphChars.Space}${GlyphChars.Dash}${GlyphChars.Space} this may take a while`
: `Show More ${itemType}`,
maxCount,
previousNode,
maxCount
pageSize
);
}
}

+ 4
- 3
src/views/nodes/contributorNode.ts View File

@ -11,8 +11,9 @@ import { CommitNode } from './commitNode';
import { GlyphChars } from '../../constants';
export class ContributorNode extends ViewNode<RepositoriesView> implements PageableViewNode {
readonly supportsPaging: boolean = true;
maxCount: number | undefined;
readonly supportsPaging = true;
readonly rememberLastMaxCount = true;
maxCount: number | undefined = this.view.getNodeLastMaxCount(this);
constructor(uri: GitUri, view: RepositoriesView, parent: ViewNode, public readonly contributor: GitContributor) {
super(uri, view, parent);
@ -41,7 +42,7 @@ export class ContributorNode extends ViewNode implements Pagea
];
if (log.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Commits', children[children.length - 1]));
children.push(new ShowMoreNode(this.view, this, 'Commits', log.maxCount, children[children.length - 1]));
}
return children;
}

+ 4
- 2
src/views/nodes/fileHistoryNode.ts View File

@ -19,7 +19,7 @@ import { insertDateMarkers } from './helpers';
import { PageableViewNode, ResourceType, SubscribeableViewNode, ViewNode } from './viewNode';
export class FileHistoryNode extends SubscribeableViewNode implements PageableViewNode {
readonly supportsPaging: boolean = true;
readonly supportsPaging = true;
maxCount: number | undefined;
constructor(uri: GitUri, view: View, parent: ViewNode) {
@ -89,7 +89,9 @@ export class FileHistoryNode extends SubscribeableViewNode implements PageableVi
);
if (log.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Commits', children[children.length - 1]));
children.push(
new ShowMoreNode(this.view, this, 'Commits', log.maxCount, children[children.length - 1])
);
}
}

+ 4
- 2
src/views/nodes/lineHistoryNode.ts View File

@ -18,7 +18,7 @@ import { insertDateMarkers } from './helpers';
import { PageableViewNode, ResourceType, SubscribeableViewNode, ViewNode } from './viewNode';
export class LineHistoryNode extends SubscribeableViewNode implements PageableViewNode {
readonly supportsPaging: boolean = true;
readonly supportsPaging = true;
maxCount: number | undefined;
constructor(
@ -111,7 +111,9 @@ export class LineHistoryNode extends SubscribeableViewNode implements PageableVi
);
if (log.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Commits', children[children.length - 1]));
children.push(
new ShowMoreNode(this.view, this, 'Commits', log.maxCount, children[children.length - 1])
);
}
}

+ 6
- 3
src/views/nodes/reflogNode.ts View File

@ -9,8 +9,9 @@ import { debug, gate } from '../../system';
import { MessageNode, ShowMoreNode } from './common';
export class ReflogNode extends ViewNode<RepositoriesView> implements PageableViewNode {
readonly supportsPaging: boolean = true;
maxCount: number | undefined;
readonly supportsPaging = true;
readonly rememberLastMaxCount = true;
maxCount: number | undefined = this.view.getNodeLastMaxCount(this);
private _children: ViewNode[] | undefined;
@ -37,7 +38,9 @@ export class ReflogNode extends ViewNode implements PageableVi
children.push(...reflog.records.map(r => new ReflogRecordNode(this.view, this, r)));
if (reflog.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Activity', children[children.length - 1]));
children.push(
new ShowMoreNode(this.view, this, 'Activity', reflog.maxCount, children[children.length - 1])
);
}
this._children = children;

+ 4
- 3
src/views/nodes/reflogRecordNode.ts View File

@ -10,8 +10,9 @@ import { MessageNode, ShowMoreNode } from './common';
import { PageableViewNode, ResourceType, ViewNode } from './viewNode';
export class ReflogRecordNode extends ViewNode<ViewWithFiles> implements PageableViewNode {
readonly supportsPaging: boolean = true;
maxCount: number | undefined;
readonly supportsPaging = true;
readonly rememberLastMaxCount = true;
maxCount: number | undefined = this.view.getNodeLastMaxCount(this);
constructor(view: ViewWithFiles, parent: ViewNode, public readonly record: GitReflogRecord) {
super(GitUri.fromRepoPath(record.repoPath), view, parent);
@ -37,7 +38,7 @@ export class ReflogRecordNode extends ViewNode implements Pageabl
];
if (log.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Commits', children[children.length - 1]));
children.push(new ShowMoreNode(this.view, this, 'Commits', log.maxCount, children[children.length - 1]));
}
return children;
}

+ 6
- 6
src/views/nodes/resultsCommitsNode.ts View File

@ -15,11 +15,9 @@ export interface CommitsQueryResults {
}
export class ResultsCommitsNode extends ViewNode<ViewWithFiles> implements PageableViewNode {
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');
readonly supportsPaging = true;
readonly rememberLastMaxCount = true;
maxCount: number | undefined = this.view.getNodeLastMaxCount(this);
constructor(
view: ViewWithFiles,
@ -58,7 +56,9 @@ export class ResultsCommitsNode extends ViewNode implements Pagea
];
if (log.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Results', children[children.length - 1], this.maxCount));
children.push(
new ShowMoreNode(this.view, this, 'Results', log.maxCount, children[children.length - 1], this.maxCount)
);
}
return children;

+ 4
- 3
src/views/nodes/tagNode.ts View File

@ -11,8 +11,9 @@ import { getBranchesAndTagTipsFn, insertDateMarkers } from './helpers';
import { PageableViewNode, ResourceType, ViewNode, ViewRefNode } from './viewNode';
export class TagNode extends ViewRefNode<RepositoriesView> implements PageableViewNode {
readonly supportsPaging: boolean = true;
maxCount: number | undefined;
readonly supportsPaging = true;
readonly rememberLastMaxCount = true;
maxCount: number | undefined = this.view.getNodeLastMaxCount(this);
constructor(uri: GitUri, view: RepositoriesView, parent: ViewNode, public readonly tag: GitTag) {
super(uri, view, parent);
@ -49,7 +50,7 @@ export class TagNode extends ViewRefNode implements PageableVi
];
if (log.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Commits', children[children.length - 1]));
children.push(new ShowMoreNode(this.view, this, 'Commits', log.maxCount, children[children.length - 1]));
}
return children;
}

+ 23
- 18
src/views/nodes/viewNode.ts View File

@ -112,23 +112,20 @@ export abstract class ViewRefFileNode extends ViewRef
}
}
export function nodeSupportsConditionalDismissal(node: ViewNode): node is ViewNode & { canDismiss(): boolean } {
return typeof (node as ViewNode & { canDismiss(): boolean }).canDismiss === 'function';
}
export interface PageableViewNode {
readonly id?: string;
readonly supportsPaging: boolean;
readonly rememberLastMaxCount?: boolean;
maxCount: number | undefined;
}
export function isPageable(node: ViewNode): node is ViewNode & PageableViewNode {
export function nodeSupportsPaging(node: ViewNode): node is ViewNode & PageableViewNode {
return Functions.is<ViewNode & PageableViewNode>(node, 'supportsPaging', true);
}
interface AutoRefreshableView {
autoRefresh: boolean;
onDidChangeAutoRefresh: Event<void>;
}
export function supportsAutoRefresh(view: View): view is View & AutoRefreshableView {
return Functions.is<View & AutoRefreshableView>(view, 'onDidChangeAutoRefresh');
}
export abstract class SubscribeableViewNode<TView extends View = View> extends ViewNode<TView> {
protected _disposable: Disposable;
protected _subscription: Promise<Disposable | undefined> | undefined;
@ -141,7 +138,7 @@ export abstract class SubscribeableViewNode extends V
this.view.onDidChangeNodeState(this.onNodeStateChanged, this)
];
if (supportsAutoRefresh(this.view)) {
if (viewSupportsAutoRefresh(this.view)) {
disposables.push(this.view.onDidChangeAutoRefresh(this.onAutoRefreshChanged, this));
}
@ -200,15 +197,15 @@ export abstract class SubscribeableViewNode extends V
if (e.element === this) {
this._state = e.state;
if (this.onStateChanged !== undefined) {
this.onStateChanged(e.state);
}
this.onStateChanged(e.state);
}
}
else if (e.element === this.parent) {
if (this.onParentStateChanged !== undefined) {
this.onParentStateChanged(e.state);
this.onParentStateChanged(e.state);
}
}
}
}
@debug()
protected onVisibilityChanged(e: TreeViewVisibilityChangeEvent) {
@ -222,7 +219,11 @@ export abstract class SubscribeableViewNode extends V
@debug()
async ensureSubscription() {
// We only need to subscribe if we are visible and if auto-refresh enabled (when supported)
if (!this.canSubscribe || !this.view.visible || (supportsAutoRefresh(this.view) && !this.view.autoRefresh)) {
if (
!this.canSubscribe ||
!this.view.visible ||
(viewSupportsAutoRefresh(this.view) && !this.view.autoRefresh)
) {
await this.unsubscribe();
return;
@ -236,8 +237,12 @@ export abstract class SubscribeableViewNode extends V
}
}
export function nodeSupportsConditionalDismissal(node: ViewNode): node is ViewNode & { canDismiss(): boolean } {
return typeof (node as ViewNode & { canDismiss(): boolean }).canDismiss === 'function';
interface AutoRefreshableView {
autoRefresh: boolean;
onDidChangeAutoRefresh: Event<void>;
}
export function viewSupportsAutoRefresh(view: View): view is View & AutoRefreshableView {
return Functions.is<View & AutoRefreshableView>(view, 'onDidChangeAutoRefresh');
}
export function viewSupportsNodeDismissal(view: View): view is View & { dismissNode(node: ViewNode): void } {

+ 55
- 20
src/views/viewBase.ts View File

@ -23,10 +23,9 @@ import { CompareView } from './compareView';
import { FileHistoryView } from './fileHistoryView';
import { LineHistoryView } from './lineHistoryView';
import { ViewNode } from './nodes';
import { isPageable } from './nodes/viewNode';
import { nodeSupportsPagingspan>, PageableViewNode } from './nodes/viewNode';
import { RepositoriesView } from './repositoriesView';
import { SearchView } from './searchView';
import { RefreshNodeCommandArgs } from './viewCommands';
export type View = RepositoriesView | FileHistoryView | LineHistoryView | CompareView | SearchView;
export type ViewWithFiles = RepositoriesView | CompareView | SearchView;
@ -52,6 +51,7 @@ export abstract class ViewBase> implements TreeData
}
protected _disposable: Disposable | undefined;
private readonly _lastMaxCounts = new Map<string, number | undefined>();
protected _root: TRoot | undefined;
protected _tree: TreeView<ViewNode> | undefined;
@ -128,6 +128,11 @@ export abstract class ViewBase> implements TreeData
}
protected onElementCollapsed(e: TreeViewExpansionEvent<ViewNode>) {
// Clear any last max count if the node was collapsed
if (nodeSupportsPaging(e.element)) {
this.resetNodeLastMaxCount(e.element);
}
this._onDidChangeNodeState.fire({ ...e, state: TreeItemCollapsibleState.Collapsed });
}
@ -161,25 +166,10 @@ export abstract class ViewBase> implements TreeData
@debug({
args: { 0: (n: ViewNode) => n.toString() }
})
async refreshNode(node: ViewNode, reset: boolean = false, args?: RefreshNodeCommandArgs) {
if (args !== undefined) {
if (isPageable(node)) {
if (args.maxCount === undefined || args.maxCount === 0) {
node.maxCount = args.maxCount;
}
else {
node.maxCount = (node.maxCount || args.maxCount) + args.maxCount;
}
if (args.previousNode !== undefined) {
void (await this.reveal(args.previousNode, { select: true }));
}
}
}
async refreshNode(node: ViewNode, reset: boolean = false) {
if (node.refresh !== undefined) {
const cancel = await node.refresh(reset);
if (cancel === true) return;
const cancel = await node.refresh(reset);
if (cancel === true) return;
}
this.triggerNodeChange(node);
@ -237,6 +227,51 @@ export abstract class ViewBase> implements TreeData
}
@debug({
args: { 0: (n: ViewNode) => n.toString() }
})
getNodeLastMaxCount(node: PageableViewNode) {
return node.id === undefined ? undefined : this._lastMaxCounts.get(node.id);
}
@debug({
args: { 0: (n: ViewNode) => n.toString() }
})
resetNodeLastMaxCount(node: PageableViewNode) {
if (node.id === undefined || !node.rememberLastMaxCount) return;
this._lastMaxCounts.delete(node.id);
}
@debug({
args: {
0: (n: ViewNode & PageableViewNode) => n.toString(),
3: (n?: ViewNode) => (n === undefined ? '' : n.toString())
}
})
async showMoreNodeChildren(
node: ViewNode & PageableViewNode,
maxCount: number | undefined,
previousNode?: ViewNode
) {
if (maxCount === undefined || maxCount === 0) {
node.maxCount = maxCount;
}
else {
node.maxCount = (node.maxCount || maxCount) + maxCount;
}
if (node.rememberLastMaxCount) {
this._lastMaxCounts.set(node.id!, node.maxCount);
}
if (previousNode !== undefined) {
void (await this.reveal(previousNode, { select: true }));
}
return this.refreshNode(node);
}
@debug({
args: { 0: (n: ViewNode) => (n != null ? n.toString() : '') }
})
triggerNodeChange(node?: ViewNode) {

+ 10
- 7
src/views/viewCommands.ts View File

@ -27,6 +27,7 @@ import {
FileHistoryNode,
FolderNode,
LineHistoryNode,
nodeSupportsPaging,
RemoteNode,
RepositoryNode,
ResultsFileNode,
@ -42,11 +43,6 @@ import {
import { Strings } from '../system/string';
import { PagerNode } from './nodes/common';
export interface RefreshNodeCommandArgs {
maxCount?: number;
previousNode?: ViewNode;
}
interface CompareSelectedInfo {
ref: string;
repoPath: string | undefined;
@ -61,8 +57,14 @@ export class ViewCommands implements Disposable {
constructor() {
commands.registerCommand(
'gitlens.views.refreshNode',
(node: ViewNode, reset?: boolean, args?: RefreshNodeCommandArgs) =>
node.view.refreshNode(node, reset === undefined ? true : reset, args),
(node: ViewNode, reset?: boolean) => {
if (reset === undefined && nodeSupportsPaging(node)) {
node.maxCount = undefined;
node.view.resetNodeLastMaxCount(node);
}
return node.view.refreshNode(node, reset === undefined ? true : reset);
},
this
);
commands.registerCommand(
@ -76,6 +78,7 @@ export class ViewCommands implements Disposable {
this
);
commands.registerCommand('gitlens.views.executeNodeCallback', (fn: <R>() => Promise<R>) => fn(), this);
commands.registerCommand('gitlens.views.showMoreChildren', (node: PagerNode) => node.showMore(), this);
commands.registerCommand('gitlens.views.showAllChildren', (node: PagerNode) => node.showAll(), this);
commands.registerCommand('gitlens.views.fetch', this.fetch, this);

Loading…
Cancel
Save