Browse Source

Adds type discriminator to ViewNode

main
Eric Amodio 1 year ago
parent
commit
b6b8f36890
56 changed files with 426 additions and 342 deletions
  1. +57
    -0
      src/constants.ts
  2. +2
    -2
      src/views/nodes/UncommittedFileNode.ts
  3. +3
    -3
      src/views/nodes/UncommittedFilesNode.ts
  4. +3
    -3
      src/views/nodes/autolinkedItemNode.ts
  5. +3
    -3
      src/views/nodes/autolinkedItemsNode.ts
  6. +6
    -3
      src/views/nodes/branchNode.ts
  7. +7
    -7
      src/views/nodes/branchOrTagFolderNode.ts
  8. +3
    -3
      src/views/nodes/branchTrackingStatusFilesNode.ts
  9. +6
    -3
      src/views/nodes/branchTrackingStatusNode.ts
  10. +3
    -3
      src/views/nodes/branchesNode.ts
  11. +30
    -11
      src/views/nodes/commitFileNode.ts
  12. +3
    -3
      src/views/nodes/commitNode.ts
  13. +4
    -72
      src/views/nodes/common.ts
  14. +3
    -3
      src/views/nodes/compareBranchNode.ts
  15. +2
    -2
      src/views/nodes/comparePickerNode.ts
  16. +3
    -3
      src/views/nodes/compareResultsNode.ts
  17. +3
    -3
      src/views/nodes/contributorNode.ts
  18. +3
    -3
      src/views/nodes/contributorsNode.ts
  19. +6
    -3
      src/views/nodes/fileHistoryNode.ts
  20. +2
    -2
      src/views/nodes/fileHistoryTrackerNode.ts
  21. +5
    -2
      src/views/nodes/fileRevisionAsCommitNode.ts
  22. +3
    -3
      src/views/nodes/folderNode.ts
  23. +3
    -3
      src/views/nodes/lineHistoryNode.ts
  24. +5
    -2
      src/views/nodes/lineHistoryTrackerNode.ts
  25. +5
    -2
      src/views/nodes/mergeConflictCurrentChangesNode.ts
  26. +2
    -2
      src/views/nodes/mergeConflictFileNode.ts
  27. +2
    -2
      src/views/nodes/mergeConflictFilesNode.ts
  28. +5
    -2
      src/views/nodes/mergeConflictIncomingChangesNode.ts
  29. +3
    -3
      src/views/nodes/mergeStatusNode.ts
  30. +3
    -3
      src/views/nodes/pullRequestNode.ts
  31. +3
    -3
      src/views/nodes/rebaseStatusNode.ts
  32. +3
    -3
      src/views/nodes/reflogNode.ts
  33. +3
    -3
      src/views/nodes/reflogRecordNode.ts
  34. +3
    -3
      src/views/nodes/remoteNode.ts
  35. +3
    -3
      src/views/nodes/remotesNode.ts
  36. +2
    -2
      src/views/nodes/repositoriesNode.ts
  37. +8
    -11
      src/views/nodes/repositoryNode.ts
  38. +3
    -3
      src/views/nodes/resultsCommitsNode.ts
  39. +3
    -3
      src/views/nodes/resultsFileNode.ts
  40. +3
    -3
      src/views/nodes/resultsFilesNode.ts
  41. +3
    -3
      src/views/nodes/searchResultsNode.ts
  42. +3
    -4
      src/views/nodes/stashFileNode.ts
  43. +3
    -3
      src/views/nodes/stashNode.ts
  44. +3
    -3
      src/views/nodes/stashesNode.ts
  45. +2
    -2
      src/views/nodes/statusFileNode.ts
  46. +3
    -3
      src/views/nodes/statusFilesNode.ts
  47. +3
    -3
      src/views/nodes/tagNode.ts
  48. +3
    -3
      src/views/nodes/tagsNode.ts
  49. +91
    -31
      src/views/nodes/viewNode.ts
  50. +3
    -3
      src/views/nodes/workspaceMissingRepositoryNode.ts
  51. +3
    -3
      src/views/nodes/workspaceNode.ts
  52. +0
    -70
      src/views/nodes/workspacesViewNode.ts
  53. +4
    -4
      src/views/nodes/worktreeNode.ts
  54. +3
    -3
      src/views/nodes/worktreesNode.ts
  55. +2
    -2
      src/views/searchAndCompareView.ts
  56. +75
    -6
      src/views/workspacesView.ts

+ 57
- 0
src/constants.ts View File

@ -509,6 +509,63 @@ export const viewIdsByDefaultContainerId = new Map
['workbench.view.extension.gitlens', ['home', 'workspaces', 'account']],
]);
export type TreeViewRefNodeTypes = 'branch' | 'commit' | 'stash' | 'tag';
export type TreeViewRefFileNodeTypes = 'commit-file' | 'file-commit' | 'results-file' | 'stash-file';
export type TreeViewFileNodeTypes =
| TreeViewRefFileNodeTypes
| 'conflict-file'
| 'folder'
| 'status-file'
| 'uncommitted-file';
export type TreeViewSubscribableNodeTypes =
| 'compare-branch'
| 'compare-results'
| 'file-history'
| 'file-history-tracker'
| 'line-history'
| 'line-history-tracker'
| 'repositories'
| 'repository'
| 'repository-folder'
| 'search-results'
| 'workspace';
export type TreeViewNodeTypes =
| TreeViewRefNodeTypes
| TreeViewFileNodeTypes
| TreeViewSubscribableNodeTypes
| 'autolink'
| 'autolinks'
| 'branch-tag-folder'
| 'branches'
| 'compare-picker'
| 'contributor'
| 'contributors'
| 'conflict-files'
| 'conflict-current-changes'
| 'conflict-incoming-changes'
| 'merge-status'
| 'message'
| 'pager'
| 'pullrequest'
| 'rebase-status'
| 'reflog'
| 'reflog-record'
| 'remote'
| 'remotes'
| 'results-commits'
| 'results-files'
| 'search-compare'
| 'stashes'
| 'status-files'
| 'tags'
| 'tracking-status'
| 'tracking-status-files'
| 'uncommitted-files'
| 'workspace-missing-repository'
| 'workspaces-view'
| 'worktree'
| 'worktrees';
export type ContextKeys =
| `${typeof extensionPrefix}:action:${string}`
| `${typeof extensionPrefix}:key:${Keys}`

+ 2
- 2
src/views/nodes/UncommittedFileNode.ts View File

@ -12,9 +12,9 @@ import type { FileNode } from './folderNode';
import type { ViewNode } from './viewNode';
import { ContextValues, ViewFileNode } from './viewNode';
export class UncommittedFileNode extends ViewFileNode<ViewsWithCommits> implements FileNode {
export class UncommittedFileNode extends ViewFileNode<'uncommitted-file', ViewsWithCommits> implements FileNode {
constructor(view: ViewsWithCommits, parent: ViewNode, repoPath: string, file: GitFile) {
super(GitUri.fromFile(file, repoPath), view, parent, file);
super('uncommitted-file', GitUri.fromFile(file, repoPath), view, parent, file);
}
override toClipboard(): string {

+ 3
- 3
src/views/nodes/UncommittedFilesNode.ts View File

@ -12,7 +12,7 @@ import { FolderNode } from './folderNode';
import { UncommittedFileNode } from './UncommittedFileNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class UncommittedFilesNode extends ViewNode<ViewsWithWorkingTree> {
export class UncommittedFilesNode extends ViewNode<'uncommitted-files', ViewsWithWorkingTree> {
constructor(
view: ViewsWithWorkingTree,
protected override readonly parent: ViewNode,
@ -26,9 +26,9 @@ export class UncommittedFilesNode extends ViewNode {
},
public readonly range: string | undefined,
) {
super(GitUri.fromRepoPath(status.repoPath), view, parent);
super('uncommitted-files', GitUri.fromRepoPath(status.repoPath), view, parent);
this._uniqueId = getViewNodeId('uncommitted-files', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

+ 3
- 3
src/views/nodes/autolinkedItemNode.ts View File

@ -8,7 +8,7 @@ import { isPromise } from '../../system/promise';
import type { ViewsWithCommits } from '../viewBase';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class AutolinkedItemNode extends ViewNode<ViewsWithCommits> {
export class AutolinkedItemNode extends ViewNode<'autolink', ViewsWithCommits> {
constructor(
view: ViewsWithCommits,
protected override readonly parent: ViewNode,
@ -16,9 +16,9 @@ export class AutolinkedItemNode extends ViewNode {
public readonly item: Autolink,
private enrichedItem: Promise<IssueOrPullRequest | undefined> | IssueOrPullRequest | undefined,
) {
super(GitUri.fromRepoPath(repoPath), view, parent);
super('autolink', GitUri.fromRepoPath(repoPath), view, parent);
this._uniqueId = getViewNodeId(`autolink+${item.id}`, this.context);
this._uniqueId = getViewNodeId(`${this.type}+${item.id}`, this.context);
}
override get id(): string {

+ 3
- 3
src/views/nodes/autolinkedItemsNode.ts View File

@ -14,7 +14,7 @@ import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
let instanceId = 0;
export class AutolinkedItemsNode extends ViewNode<ViewsWithCommits> {
export class AutolinkedItemsNode extends ViewNode<'autolinks', ViewsWithCommits> {
private _instanceId: number;
constructor(
@ -24,11 +24,11 @@ export class AutolinkedItemsNode extends ViewNode {
public readonly log: GitLog,
private expand: boolean,
) {
super(GitUri.fromRepoPath(repoPath), view, parent);
super('autolinks', GitUri.fromRepoPath(repoPath), view, parent);
this._instanceId = instanceId++;
this.updateContext({ autolinksId: String(this._instanceId) });
this._uniqueId = getViewNodeId('autolinks', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

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

@ -34,7 +34,10 @@ type State = {
pendingPullRequest: Promise<PullRequest | undefined> | undefined;
};
export class BranchNode extends ViewRefNode<ViewsWithBranches, GitBranchReference, State> implements PageableViewNode {
export class BranchNode
extends ViewRefNode<'branch', ViewsWithBranches, GitBranchReference, State>
implements PageableViewNode
{
limit: number | undefined;
private readonly options: {
@ -68,10 +71,10 @@ export class BranchNode extends ViewRefNode
authors?: GitUser[];
},
) {
super(uri, view, parent);
super('branch', uri, view, parent);
this.updateContext({ repository: repo, branch: branch, root: root });
this._uniqueId = getViewNodeId('branch', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this.limit = this.view.getNodeLastKnownLimit(this);
this.options = {

+ 7
- 7
src/views/nodes/branchOrTagFolderNode.ts View File

@ -2,24 +2,24 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { GitUri } from '../../git/gitUri';
import type { HierarchicalItem } from '../../system/array';
import type { View } from '../viewBase';
import { BranchNode } from './branchNode';
import type { BranchNode } from './branchNode';
import type { TagNode } from './tagNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class BranchOrTagFolderNode extends ViewNode {
export class BranchOrTagFolderNode extends ViewNode<'branch-tag-folder'> {
constructor(
view: View,
protected override readonly parent: ViewNode,
public readonly type: 'branch' | 'remote-branch' | 'tag',
public readonly folderType: 'branch' | 'remote-branch' | 'tag',
public readonly root: HierarchicalItem<BranchNode | TagNode>,
public readonly repoPath: string,
public readonly folderName: string,
public readonly relativePath: string | undefined,
private readonly _expanded: boolean = false,
) {
super(GitUri.fromRepoPath(repoPath), view, parent);
super('branch-tag-folder', GitUri.fromRepoPath(repoPath), view, parent);
this._uniqueId = getViewNodeId(`${type}-folder+${relativePath ?? folderName}`, this.context);
this._uniqueId = getViewNodeId(`${this.type}+${folderType}+${relativePath ?? folderName}`, this.context);
}
override get id(): string {
@ -38,12 +38,12 @@ export class BranchOrTagFolderNode extends ViewNode {
for (const folder of this.root.children.values()) {
if (folder.value === undefined) {
// If the folder contains the current branch, expand it by default
const expanded = folder.descendants?.some(n => n instanceof BranchNode && n.current);
const expanded = folder.descendants?.some(n => n.is('branch') && n.current);
children.push(
new BranchOrTagFolderNode(
this.view,
this.folderName ? this : this.parent,
this.type,
this.folderType,
folder,
this.repoPath,
folder.name,

+ 3
- 3
src/views/nodes/branchTrackingStatusFilesNode.ts View File

@ -14,7 +14,7 @@ import { FolderNode } from './folderNode';
import { StatusFileNode } from './statusFileNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class BranchTrackingStatusFilesNode extends ViewNode<ViewsWithCommits> {
export class BranchTrackingStatusFilesNode extends ViewNode<'tracking-status-files', ViewsWithCommits> {
constructor(
view: ViewsWithCommits,
protected override readonly parent: ViewNode,
@ -22,10 +22,10 @@ export class BranchTrackingStatusFilesNode extends ViewNode {
public readonly status: Required<BranchTrackingStatus>,
public readonly direction: 'ahead' | 'behind',
) {
super(GitUri.fromRepoPath(status.repoPath), view, parent);
super('tracking-status-files', GitUri.fromRepoPath(status.repoPath), view, parent);
this.updateContext({ branch: branch, branchStatus: status, branchStatusUpstreamType: direction });
this._uniqueId = getViewNodeId('tracking-status-files', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
get repoPath(): string {

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

@ -26,7 +26,10 @@ export interface BranchTrackingStatus {
upstream?: string;
}
export class BranchTrackingStatusNode extends ViewNode<ViewsWithCommits> implements PageableViewNode {
export class BranchTrackingStatusNode
extends ViewNode<'tracking-status', ViewsWithCommits>
implements PageableViewNode
{
limit: number | undefined;
constructor(
@ -41,7 +44,7 @@ export class BranchTrackingStatusNode extends ViewNode impleme
showAheadCommits?: boolean;
},
) {
super(GitUri.fromRepoPath(status.repoPath), view, parent);
super('tracking-status', GitUri.fromRepoPath(status.repoPath), view, parent);
this.updateContext({
branch: branch,
@ -49,7 +52,7 @@ export class BranchTrackingStatusNode extends ViewNode impleme
branchStatusUpstreamType: upstreamType,
root: root,
});
this._uniqueId = getViewNodeId('tracking-status', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this.limit = this.view.getNodeLastKnownLimit(this);
}

+ 3
- 3
src/views/nodes/branchesNode.ts View File

@ -10,17 +10,17 @@ import { BranchOrTagFolderNode } from './branchOrTagFolderNode';
import { MessageNode } from './common';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class BranchesNode extends ViewNode<ViewsWithBranchesNode> {
export class BranchesNode extends ViewNode<'branches', ViewsWithBranchesNode> {
constructor(
uri: GitUri,
view: ViewsWithBranchesNode,
protected override readonly parent: ViewNode,
public readonly repo: Repository,
) {
super(uri, view, parent);
super('branches', uri, view, parent);
this.updateContext({ repository: repo });
this._uniqueId = getViewNodeId('branches', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

+ 30
- 11
src/views/nodes/commitFileNode.ts View File

@ -1,6 +1,7 @@
import type { Command, Selection } from 'vscode';
import { MarkdownString, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
import type { DiffWithPreviousCommandArgs } from '../../commands/diffWithPrevious';
import type { TreeViewRefFileNodeTypes } from '../../constants';
import { Commands, Schemes } from '../../constants';
import { StatusFileFormatter } from '../../git/formatters/statusFormatter';
import { GitUri } from '../../git/gitUri';
@ -14,24 +15,26 @@ import type { ViewsWithCommits, ViewsWithStashes } from '../viewBase';
import type { ViewNode } from './viewNode';
import { ContextValues, getViewNodeId, ViewRefFileNode } from './viewNode';
export class CommitFileNode<
TView extends ViewsWithCommits | ViewsWithStashes = ViewsWithCommits,
> extends ViewRefFileNode<TView> {
export abstract class CommitFileNodeBase<
Type extends TreeViewRefFileNodeTypes,
TView extends ViewsWithCommits | ViewsWithStashes,
> extends ViewRefFileNode<Type, TView> {
constructor(
type: Type,
view: TView,
parent: ViewNode,
file: GitFile,
public commit: GitCommit,
private readonly _options: {
private readonly options?: {
branch?: GitBranch;
selection?: Selection;
unpublished?: boolean;
} = {},
},
) {
super(GitUri.fromFile(file, commit.repoPath, commit.sha), view, parent, file);
super(type, GitUri.fromFile(file, commit.repoPath, commit.sha), view, parent, file);
this.updateContext({ commit: commit, file: file });
this._uniqueId = getViewNodeId('commit-file', this.context);
this._uniqueId = getViewNodeId(type, this.context);
}
override get id(): string {
@ -106,9 +109,9 @@ export class CommitFileNode<
protected get contextValue(): string {
if (!this.commit.isUncommitted) {
return `${ContextValues.File}+committed${this._options.branch?.current ? '+current' : ''}${
this._options.branch?.current && this._options.branch.sha === this.commit.ref ? '+HEAD' : ''
}${this._options.unpublished ? '+unpublished' : ''}`;
return `${ContextValues.File}+committed${this.options?.branch?.current ? '+current' : ''}${
this.options?.branch?.current && this.options.branch.sha === this.commit.ref ? '+HEAD' : ''
}${this.options?.unpublished ? '+unpublished' : ''}`;
}
return this.commit.isUncommittedStaged ? `${ContextValues.File}+staged` : `${ContextValues.File}+unstaged`;
@ -165,7 +168,7 @@ export class CommitFileNode<
if (this.commit.lines.length) {
line = this.commit.lines[0].line - 1;
} else {
line = this._options.selection?.active.line ?? 0;
line = this.options?.selection?.active.line ?? 0;
}
const commandArgs: DiffWithPreviousCommandArgs = {
@ -184,3 +187,19 @@ export class CommitFileNode<
};
}
}
export class CommitFileNode extends CommitFileNodeBase<'commit-file', ViewsWithCommits> {
constructor(
view: ViewsWithCommits,
parent: ViewNode,
file: GitFile,
commit: GitCommit,
options?: {
branch?: GitBranch;
selection?: Selection;
unpublished?: boolean;
},
) {
super('commit-file', view, parent, file, commit, options);
}
}

+ 3
- 3
src/views/nodes/commitNode.ts View File

@ -33,7 +33,7 @@ type State = {
pendingPullRequest: Promise<PullRequest | undefined> | undefined;
};
export class CommitNode extends ViewRefNode<ViewsWithCommits | FileHistoryView, GitRevisionReference, State> {
export class CommitNode extends ViewRefNode<'commit', ViewsWithCommits | FileHistoryView, GitRevisionReference, State> {
constructor(
view: ViewsWithCommits | FileHistoryView,
parent: ViewNode,
@ -43,10 +43,10 @@ export class CommitNode extends ViewRefNode
protected readonly getBranchAndTagTips?: (sha: string, options?: { compact?: boolean }) => string | undefined,
protected readonly _options: { expand?: boolean } = {},
) {
super(commit.getGitUri(), view, parent);
super('commit', commit.getGitUri(), view, parent);
this.updateContext({ commit: commit });
this._uniqueId = getViewNodeId('commit', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

+ 4
- 72
src/views/nodes/common.ts View File

@ -7,7 +7,7 @@ import type { View } from '../viewBase';
import type { PageableViewNode } from './viewNode';
import { ContextValues, ViewNode } from './viewNode';
export class MessageNode extends ViewNode {
export class MessageNode extends ViewNode<'message'> {
constructor(
view: View,
protected override readonly parent: ViewNode,
@ -24,7 +24,7 @@ export class MessageNode extends ViewNode {
| ThemeIcon,
private readonly _contextValue?: string,
) {
super(unknownGitUri, view, parent);
super('message', unknownGitUri, view, parent);
}
getChildren(): ViewNode[] | Promise<ViewNode[]> {
@ -75,75 +75,7 @@ export class CommandMessageNode extends MessageNode {
}
}
export class UpdateableMessageNode extends ViewNode {
constructor(
view: View,
protected override readonly parent: ViewNode,
private _id: string,
private _message: string,
private _tooltip?: string,
private _iconPath?:
| string
| Uri
| {
light: string | Uri;
dark: string | Uri;
}
| ThemeIcon,
) {
super(unknownGitUri, view, parent);
}
override get id(): string {
return this._id;
}
getChildren(): ViewNode[] | Promise<ViewNode[]> {
return [];
}
getTreeItem(): TreeItem | Promise<TreeItem> {
const item = new TreeItem(this._message, TreeItemCollapsibleState.None);
item.id = this.id;
item.contextValue = ContextValues.Message;
item.tooltip = this._tooltip;
item.iconPath = this._iconPath;
return item;
}
update(
changes: {
message?: string;
tooltip?: string | null;
iconPath?:
| string
| null
| Uri
| {
light: string | Uri;
dark: string | Uri;
}
| ThemeIcon;
},
view: View,
) {
if (changes.message !== undefined) {
this._message = changes.message;
}
if (changes.tooltip !== undefined) {
this._tooltip = changes.tooltip === null ? undefined : changes.tooltip;
}
if (changes.iconPath !== undefined) {
this._iconPath = changes.iconPath === null ? undefined : changes.iconPath;
}
view.triggerNodeChange(this);
}
}
export abstract class PagerNode extends ViewNode {
export abstract class PagerNode extends ViewNode<'pager'> {
constructor(
view: View,
parent: ViewNode & PageableViewNode,
@ -155,7 +87,7 @@ export abstract class PagerNode extends ViewNode {
getCount?: () => Promise<number | undefined>;
}, // protected readonly pageSize: number = configuration.get('views.pageItemLimit'), // protected readonly countFn?: () => Promise<number | undefined>, // protected readonly context?: Record<string, unknown>, // protected readonly beforeLoadCallback?: (mode: 'all' | 'more') => void,
) {
super(unknownGitUri, view, parent);
super('pager', unknownGitUri, view, parent);
}
async loadAll() {

+ 3
- 3
src/views/nodes/compareBranchNode.ts View File

@ -27,7 +27,7 @@ import { ResultsFilesNode } from './resultsFilesNode';
import type { ViewNode } from './viewNode';
import { ContextValues, getViewNodeId, SubscribeableViewNode } from './viewNode';
export class CompareBranchNode extends SubscribeableViewNode<ViewsWithBranches | WorktreesView> {
export class CompareBranchNode extends SubscribeableViewNode<'compare-branch', ViewsWithBranches | WorktreesView> {
private _children: ViewNode[] | undefined;
private _compareWith: StoredBranchComparison | undefined;
@ -40,10 +40,10 @@ export class CompareBranchNode extends SubscribeableViewNode
// Specifies that the node is shown as a root
public readonly root: boolean = false,
) {
super(uri, view, parent);
super('compare-branch', uri, view, parent);
this.updateContext({ branch: branch, root: root, storedComparisonId: this.getStorageId() });
this._uniqueId = getViewNodeId('compare-branch', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this.loadCompareWith();
}

+ 2
- 2
src/views/nodes/comparePickerNode.ts View File

@ -11,7 +11,7 @@ interface RepoRef {
ref: string | StoredNamedRef;
}
export class ComparePickerNode extends ViewNode<SearchAndCompareView> {
export class ComparePickerNode extends ViewNode<'compare-picker', SearchAndCompareView> {
readonly order: number = Date.now();
constructor(
@ -19,7 +19,7 @@ export class ComparePickerNode extends ViewNode {
parent: SearchAndCompareViewNode,
public readonly selectedRef: RepoRef,
) {
super(unknownGitUri, view, parent);
super('compare-picker', unknownGitUri, view, parent);
}
getChildren(): ViewNode[] {

+ 3
- 3
src/views/nodes/compareResultsNode.ts View File

@ -19,7 +19,7 @@ import { ContextValues, getViewNodeId, SubscribeableViewNode } from './viewNode'
let instanceId = 0;
export class CompareResultsNode extends SubscribeableViewNode<SearchAndCompareView> {
export class CompareResultsNode extends SubscribeableViewNode<'compare-results', SearchAndCompareView> {
private _instanceId: number;
constructor(
@ -30,14 +30,14 @@ export class CompareResultsNode extends SubscribeableViewNode
private _compareWith: StoredNamedRef,
private _storedAt: number = 0,
) {
super(GitUri.fromRepoPath(repoPath), view, parent);
super('compare-results', GitUri.fromRepoPath(repoPath), view, parent);
this._instanceId = instanceId++;
this.updateContext({
comparisonId: `${_ref.ref}+${_compareWith.ref}+${this._instanceId}`,
storedComparisonId: this.getStorageId(),
});
this._uniqueId = getViewNodeId('comparison-results', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
// If this is a new comparison, save it
if (this._storedAt === 0) {

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

@ -17,7 +17,7 @@ import { insertDateMarkers } from './helpers';
import type { PageableViewNode } from './viewNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class ContributorNode extends ViewNode<ViewsWithContributors> implements PageableViewNode {
export class ContributorNode extends ViewNode<'contributor', ViewsWithContributors> implements PageableViewNode {
limit: number | undefined;
constructor(
@ -31,10 +31,10 @@ export class ContributorNode extends ViewNode implements
presence: Map<string, ContactPresence> | undefined;
},
) {
super(uri, view, parent);
super('contributor', uri, view, parent);
this.updateContext({ contributor: contributor });
this._uniqueId = getViewNodeId('contributor', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this.limit = this.view.getNodeLastKnownLimit(this);
}

+ 3
- 3
src/views/nodes/contributorsNode.ts View File

@ -11,7 +11,7 @@ import { MessageNode } from './common';
import { ContributorNode } from './contributorNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class ContributorsNode extends ViewNode<ViewsWithContributorsNode> {
export class ContributorsNode extends ViewNode<'contributors', ViewsWithContributorsNode> {
protected override splatted = true;
constructor(
@ -20,10 +20,10 @@ export class ContributorsNode extends ViewNode {
protected override readonly parent: ViewNode,
public readonly repo: Repository,
) {
super(uri, view, parent);
super('contributors', uri, view, parent);
this.updateContext({ repository: repo });
this._uniqueId = getViewNodeId('contributors', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

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

@ -21,7 +21,10 @@ import { insertDateMarkers } from './helpers';
import type { PageableViewNode, ViewNode } from './viewNode';
import { ContextValues, getViewNodeId, SubscribeableViewNode } from './viewNode';
export class FileHistoryNode extends SubscribeableViewNode<FileHistoryView> implements PageableViewNode {
export class FileHistoryNode
extends SubscribeableViewNode<'file-history', FileHistoryView>
implements PageableViewNode
{
limit: number | undefined;
protected override splatted = true;
@ -33,12 +36,12 @@ export class FileHistoryNode extends SubscribeableViewNode impl
private readonly folder: boolean,
private readonly branch: GitBranch | undefined,
) {
super(uri, view, parent);
super('file-history', uri, view, parent);
if (branch != null) {
this.updateContext({ branch: branch });
}
this._uniqueId = getViewNodeId(`file-history+${uri.toString()}`, this.context);
this._uniqueId = getViewNodeId(`${this.type}+${uri.toString()}`, this.context);
this.limit = this.view.getNodeLastKnownLimit(this);
}

+ 2
- 2
src/views/nodes/fileHistoryTrackerNode.ts View File

@ -18,13 +18,13 @@ import { FileHistoryNode } from './fileHistoryNode';
import type { ViewNode } from './viewNode';
import { ContextValues, SubscribeableViewNode } from './viewNode';
export class FileHistoryTrackerNode extends SubscribeableViewNode<FileHistoryView> {
export class FileHistoryTrackerNode extends SubscribeableViewNode<'file-history-tracker', FileHistoryView> {
private _base: string | undefined;
private _child: FileHistoryNode | undefined;
protected override splatted = true;
constructor(view: FileHistoryView) {
super(unknownGitUri, view);
super('file-history-tracker', unknownGitUri, view);
}
override dispose() {

+ 5
- 2
src/views/nodes/fileRevisionAsCommitNode.ts View File

@ -24,7 +24,10 @@ import { MergeConflictIncomingChangesNode } from './mergeConflictIncomingChanges
import type { ViewNode } from './viewNode';
import { ContextValues, ViewRefFileNode } from './viewNode';
export class FileRevisionAsCommitNode extends ViewRefFileNode<ViewsWithCommits | FileHistoryView | LineHistoryView> {
export class FileRevisionAsCommitNode extends ViewRefFileNode<
'file-commit',
ViewsWithCommits | FileHistoryView | LineHistoryView
> {
constructor(
view: ViewsWithCommits | FileHistoryView | LineHistoryView,
parent: ViewNode,
@ -37,7 +40,7 @@ export class FileRevisionAsCommitNode extends ViewRefFileNode
unpublished?: boolean;
} = {},
) {
super(GitUri.fromFile(file, commit.repoPath, commit.sha), view, parent, file);
super('file-commit', GitUri.fromFile(file, commit.repoPath, commit.sha), view, parent, file);
}
override toClipboard(): string {

+ 3
- 3
src/views/nodes/folderNode.ts View File

@ -18,7 +18,7 @@ export interface FileNode extends ViewFileNode {
// root?: HierarchicalItem<FileNode>;
}
export class FolderNode extends ViewNode<ViewsWithCommits | StashesView> {
export class FolderNode extends ViewNode<'folder', ViewsWithCommits | StashesView> {
readonly priority: number = 1;
constructor(
@ -30,9 +30,9 @@ export class FolderNode extends ViewNode {
public readonly relativePath: string | undefined,
private readonly containsWorkingFiles?: boolean,
) {
super(GitUri.fromRepoPath(repoPath), view, parent);
super('folder', GitUri.fromRepoPath(repoPath), view, parent);
this._uniqueId = getViewNodeId(`folder+${relativePath ?? folderName}`, this.context);
this._uniqueId = getViewNodeId(`${this.type}+${relativePath ?? folderName}`, this.context);
}
override get id(): string {

+ 3
- 3
src/views/nodes/lineHistoryNode.ts View File

@ -23,7 +23,7 @@ import type { PageableViewNode, ViewNode } from './viewNode';
import { ContextValues, getViewNodeId, SubscribeableViewNode } from './viewNode';
export class LineHistoryNode
extends SubscribeableViewNode<FileHistoryView | LineHistoryView>
extends SubscribeableViewNode<'line-history', FileHistoryView | LineHistoryView>
implements PageableViewNode
{
limit: number | undefined;
@ -38,13 +38,13 @@ export class LineHistoryNode
public readonly selection: Selection,
private readonly editorContents: string | undefined,
) {
super(uri, view, parent);
super('line-history', uri, view, parent);
if (branch != null) {
this.updateContext({ branch: branch });
}
this._uniqueId = getViewNodeId(
`file-history+${uri.toString()}+[${selection.start.line},${selection.start.character}-${
`${this.type}+${uri.toString()}+[${selection.start.line},${selection.start.character}-${
selection.end.line
},${selection.end.character}]`,
this.context,

+ 5
- 2
src/views/nodes/lineHistoryTrackerNode.ts View File

@ -19,7 +19,10 @@ import { LineHistoryNode } from './lineHistoryNode';
import type { ViewNode } from './viewNode';
import { ContextValues, SubscribeableViewNode } from './viewNode';
export class LineHistoryTrackerNode extends SubscribeableViewNode<FileHistoryView | LineHistoryView> {
export class LineHistoryTrackerNode extends SubscribeableViewNode<
'line-history-tracker',
FileHistoryView | LineHistoryView
> {
private _base: string | undefined;
private _child: LineHistoryNode | undefined;
private _editorContents: string | undefined;
@ -27,7 +30,7 @@ export class LineHistoryTrackerNode extends SubscribeableViewNode
protected override splatted = true;
constructor(view: FileHistoryView | LineHistoryView) {
super(unknownGitUri, view);
super('line-history-tracker', unknownGitUri, view);
}
override dispose() {

+ 5
- 2
src/views/nodes/mergeConflictCurrentChangesNode.ts View File

@ -16,14 +16,17 @@ import type { ViewsWithCommits } from '../viewBase';
import { getFileRevisionAsCommitTooltip } from './fileRevisionAsCommitNode';
import { ContextValues, ViewNode } from './viewNode';
export class MergeConflictCurrentChangesNode extends ViewNode<ViewsWithCommits | FileHistoryView | LineHistoryView> {
export class MergeConflictCurrentChangesNode extends ViewNode<
'conflict-current-changes',
ViewsWithCommits | FileHistoryView | LineHistoryView
> {
constructor(
view: ViewsWithCommits | FileHistoryView | LineHistoryView,
protected override readonly parent: ViewNode,
private readonly status: GitMergeStatus | GitRebaseStatus,
private readonly file: GitFile,
) {
super(GitUri.fromFile(file, status.repoPath, 'HEAD'), view, parent);
super('conflict-current-changes', GitUri.fromFile(file, status.repoPath, 'HEAD'), view, parent);
}
private _commit: Promise<GitCommit | undefined> | undefined;

+ 2
- 2
src/views/nodes/mergeConflictFileNode.ts View File

@ -14,14 +14,14 @@ import { MergeConflictIncomingChangesNode } from './mergeConflictIncomingChanges
import type { ViewNode } from './viewNode';
import { ContextValues, ViewFileNode } from './viewNode';
export class MergeConflictFileNode extends ViewFileNode<ViewsWithCommits> implements FileNode {
export class MergeConflictFileNode extends ViewFileNode<'conflict-file', ViewsWithCommits> implements FileNode {
constructor(
view: ViewsWithCommits,
parent: ViewNode,
file: GitFile,
public readonly status: GitMergeStatus | GitRebaseStatus,
) {
super(GitUri.fromFile(file, status.repoPath, status.HEAD.ref), view, parent, file);
super('conflict-file', GitUri.fromFile(file, status.repoPath, status.HEAD.ref), view, parent, file);
}
override toClipboard(): string {

+ 2
- 2
src/views/nodes/mergeConflictFilesNode.ts View File

@ -12,14 +12,14 @@ import { FolderNode } from './folderNode';
import { MergeConflictFileNode } from './mergeConflictFileNode';
import { ViewNode } from './viewNode';
export class MergeConflictFilesNode extends ViewNode<ViewsWithCommits> {
export class MergeConflictFilesNode extends ViewNode<'conflict-files', ViewsWithCommits> {
constructor(
view: ViewsWithCommits,
protected override readonly parent: ViewNode,
private readonly status: GitMergeStatus | GitRebaseStatus,
private readonly conflicts: GitStatusFile[],
) {
super(GitUri.fromRepoPath(status.repoPath), view, parent);
super('conflict-files', GitUri.fromRepoPath(status.repoPath), view, parent);
}
get repoPath(): string {

+ 5
- 2
src/views/nodes/mergeConflictIncomingChangesNode.ts View File

@ -16,14 +16,17 @@ import type { ViewsWithCommits } from '../viewBase';
import { getFileRevisionAsCommitTooltip } from './fileRevisionAsCommitNode';
import { ContextValues, ViewNode } from './viewNode';
export class MergeConflictIncomingChangesNode extends ViewNode<ViewsWithCommits | FileHistoryView | LineHistoryView> {
export class MergeConflictIncomingChangesNode extends ViewNode<
'conflict-incoming-changes',
ViewsWithCommits | FileHistoryView | LineHistoryView
> {
constructor(
view: ViewsWithCommits | FileHistoryView | LineHistoryView,
protected override readonly parent: ViewNode,
private readonly status: GitMergeStatus | GitRebaseStatus,
private readonly file: GitFile,
) {
super(GitUri.fromFile(file, status.repoPath, status.HEAD.ref), view, parent);
super('conflict-incoming-changes', GitUri.fromFile(file, status.repoPath, status.HEAD.ref), view, parent);
}
private _commit: Promise<GitCommit | undefined> | undefined;

+ 3
- 3
src/views/nodes/mergeStatusNode.ts View File

@ -10,7 +10,7 @@ import type { ViewsWithCommits } from '../viewBase';
import { MergeConflictFilesNode } from './mergeConflictFilesNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class MergeStatusNode extends ViewNode<ViewsWithCommits> {
export class MergeStatusNode extends ViewNode<'merge-status', ViewsWithCommits> {
constructor(
view: ViewsWithCommits,
protected override readonly parent: ViewNode,
@ -20,10 +20,10 @@ export class MergeStatusNode extends ViewNode {
// Specifies that the node is shown as a root
public readonly root: boolean,
) {
super(GitUri.fromRepoPath(mergeStatus.repoPath), view, parent);
super('merge-status', GitUri.fromRepoPath(mergeStatus.repoPath), view, parent);
this.updateContext({ branch: branch, root: root, status: 'merging' });
this._uniqueId = getViewNodeId('merge-status', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
get repoPath(): string {

+ 3
- 3
src/views/nodes/pullRequestNode.ts View File

@ -7,7 +7,7 @@ import type { PullRequest } from '../../git/models/pullRequest';
import type { ViewsWithCommits } from '../viewBase';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class PullRequestNode extends ViewNode<ViewsWithCommits> {
export class PullRequestNode extends ViewNode<'pullrequest', ViewsWithCommits> {
readonly repoPath: string;
constructor(
@ -25,7 +25,7 @@ export class PullRequestNode extends ViewNode {
branchOrCommit = branchOrCommitOrRepoPath;
}
super(GitUri.fromRepoPath(repoPath), view, parent);
super('pullrequest', GitUri.fromRepoPath(repoPath), view, parent);
if (branchOrCommit != null) {
if (branchOrCommit instanceof GitBranch) {
@ -35,7 +35,7 @@ export class PullRequestNode extends ViewNode {
}
}
this._uniqueId = getViewNodeId('pullrequest', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this.repoPath = repoPath;
}

+ 3
- 3
src/views/nodes/rebaseStatusNode.ts View File

@ -12,7 +12,7 @@ import { MergeConflictFilesNode } from './mergeConflictFilesNode';
import { RebaseCommitNode } from './rebaseCommitNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class RebaseStatusNode extends ViewNode<ViewsWithCommits> {
export class RebaseStatusNode extends ViewNode<'rebase-status', ViewsWithCommits> {
constructor(
view: ViewsWithCommits,
protected override readonly parent: ViewNode,
@ -22,10 +22,10 @@ export class RebaseStatusNode extends ViewNode {
// Specifies that the node is shown as a root
public readonly root: boolean,
) {
super(GitUri.fromRepoPath(rebaseStatus.repoPath), view, parent);
super('rebase-status', GitUri.fromRepoPath(rebaseStatus.repoPath), view, parent);
this.updateContext({ branch: branch, root: root, status: 'rebasing' });
this._uniqueId = getViewNodeId('merge-status', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
get repoPath(): string {

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

@ -11,7 +11,7 @@ import { ReflogRecordNode } from './reflogRecordNode';
import type { PageableViewNode } from './viewNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class ReflogNode extends ViewNode<RepositoriesView | WorkspacesView> implements PageableViewNode {
export class ReflogNode extends ViewNode<'reflog', RepositoriesView | WorkspacesView> implements PageableViewNode {
limit: number | undefined;
constructor(
@ -20,10 +20,10 @@ export class ReflogNode extends ViewNode impl
parent: ViewNode,
public readonly repo: Repository,
) {
super(uri, view, parent);
super('reflog', uri, view, parent);
this.updateContext({ repository: repo });
this._uniqueId = getViewNodeId('reflog', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this.limit = this.view.getNodeLastKnownLimit(this);
}

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

@ -12,7 +12,7 @@ import { LoadMoreNode, MessageNode } from './common';
import type { PageableViewNode } from './viewNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class ReflogRecordNode extends ViewNode<ViewsWithCommits> implements PageableViewNode {
export class ReflogRecordNode extends ViewNode<'reflog-record', ViewsWithCommits> implements PageableViewNode {
limit: number | undefined;
constructor(
@ -20,10 +20,10 @@ export class ReflogRecordNode extends ViewNode implements Page
parent: ViewNode,
public readonly record: GitReflogRecord,
) {
super(GitUri.fromRepoPath(record.repoPath), view, parent);
super('reflog-record', GitUri.fromRepoPath(record.repoPath), view, parent);
this.updateContext({ reflog: record });
this._uniqueId = getViewNodeId('reflog-record', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this.limit = this.view.getNodeLastKnownLimit(this);
}

+ 3
- 3
src/views/nodes/remoteNode.ts View File

@ -12,7 +12,7 @@ import { BranchOrTagFolderNode } from './branchOrTagFolderNode';
import { MessageNode } from './common';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class RemoteNode extends ViewNode<ViewsWithRemotes> {
export class RemoteNode extends ViewNode<'remote', ViewsWithRemotes> {
constructor(
uri: GitUri,
view: ViewsWithRemotes,
@ -20,10 +20,10 @@ export class RemoteNode extends ViewNode {
public readonly repo: Repository,
public readonly remote: GitRemote,
) {
super(uri, view, parent);
super('remote', uri, view, parent);
this.updateContext({ repository: repo, remote: remote });
this._uniqueId = getViewNodeId('remote', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

+ 3
- 3
src/views/nodes/remotesNode.ts View File

@ -8,17 +8,17 @@ import { MessageNode } from './common';
import { RemoteNode } from './remoteNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class RemotesNode extends ViewNode<ViewsWithRemotesNode> {
export class RemotesNode extends ViewNode<'remotes', ViewsWithRemotesNode> {
constructor(
uri: GitUri,
view: ViewsWithRemotesNode,
protected override readonly parent: ViewNode,
public readonly repo: Repository,
) {
super(uri, view, parent);
super('remotes', uri, view, parent);
this.updateContext({ repository: repo });
this._uniqueId = getViewNodeId('remotes', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

+ 2
- 2
src/views/nodes/repositoriesNode.ts View File

@ -12,11 +12,11 @@ import { RepositoryNode } from './repositoryNode';
import type { ViewNode } from './viewNode';
import { ContextValues, SubscribeableViewNode } from './viewNode';
export class RepositoriesNode extends SubscribeableViewNode<ViewsWithRepositoriesNode> {
export class RepositoriesNode extends SubscribeableViewNode<'repositories', ViewsWithRepositoriesNode> {
private _children: (RepositoryNode | MessageNode)[] | undefined;
constructor(view: ViewsWithRepositoriesNode) {
super(unknownGitUri, view);
super('repositories', unknownGitUri, view);
}
override dispose() {

+ 8
- 11
src/views/nodes/repositoryNode.ts View File

@ -36,7 +36,7 @@ import type { AmbientContext, ViewNode } from './viewNode';
import { ContextValues, getViewNodeId, SubscribeableViewNode } from './viewNode';
import { WorktreesNode } from './worktreesNode';
export class RepositoryNode extends SubscribeableViewNode<ViewsWithRepositories> {
export class RepositoryNode extends SubscribeableViewNode<'repository', ViewsWithRepositories> {
private _children: ViewNode[] | undefined;
private _status: Promise<GitStatus | undefined>;
@ -47,10 +47,10 @@ export class RepositoryNode extends SubscribeableViewNode
public readonly repo: Repository,
context?: AmbientContext,
) {
super(uri, view, parent);
super('repository', uri, view, parent);
this.updateContext({ ...context, repository: this.repo });
this._uniqueId = getViewNodeId('repository', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this._status = this.repo.getStatus();
}
@ -423,14 +423,11 @@ export class RepositoryNode extends SubscribeableViewNode
if (this._children !== undefined) {
const status = await this._status;
let index = this._children.findIndex(c => c instanceof StatusFilesNode);
let index = this._children.findIndex(c => c.type === 'status-files');
if (status !== undefined && (status.state.ahead || status.files.length !== 0)) {
let deleteCount = 1;
if (index === -1) {
index = findLastIndex(
this._children,
c => c instanceof BranchTrackingStatusNode || c instanceof BranchNode,
);
index = findLastIndex(this._children, c => c.type === 'tracking-status' || c.type === 'branch');
deleteCount = 0;
index++;
}
@ -471,21 +468,21 @@ export class RepositoryNode extends SubscribeableViewNode
}
if (e.changed(RepositoryChange.Remotes, RepositoryChange.RemoteProviders, RepositoryChangeComparisonMode.Any)) {
const node = this._children.find(c => c instanceof RemotesNode);
const node = this._children.find(c => c.type === 'remotes');
if (node != null) {
this.view.triggerNodeChange(node);
}
}
if (e.changed(RepositoryChange.Stash, RepositoryChangeComparisonMode.Any)) {
const node = this._children.find(c => c instanceof StashesNode);
const node = this._children.find(c => c.type === 'stashes');
if (node != null) {
this.view.triggerNodeChange(node);
}
}
if (e.changed(RepositoryChange.Tags, RepositoryChangeComparisonMode.Any)) {
const node = this._children.find(c => c instanceof TagsNode);
const node = this._children.find(c => c.type === 'tags');
if (node != null) {
this.view.triggerNodeChange(node);
}

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

@ -27,7 +27,7 @@ export interface CommitsQueryResults {
}
export class ResultsCommitsNode<View extends ViewsWithCommits = ViewsWithCommits>
extends ViewNode<View>
extends ViewNode<'results-commits', View>
implements PageableViewNode
{
limit: number | undefined;
@ -51,12 +51,12 @@ export class ResultsCommitsNode
private readonly _options: { description?: string; expand?: boolean } = undefined!,
splatted?: boolean,
) {
super(GitUri.fromRepoPath(repoPath), view, parent);
super('results-commits', GitUri.fromRepoPath(repoPath), view, parent);
if (_results.direction != null) {
this.updateContext({ branchStatusUpstreamType: _results.direction });
}
this._uniqueId = getViewNodeId('results-commits', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this.limit = this.view.getNodeLastKnownLimit(this);
this._options = { expand: true, ..._options };

+ 3
- 3
src/views/nodes/resultsFileNode.ts View File

@ -19,7 +19,7 @@ type State = {
checked: TreeItemCheckboxState;
};
export class ResultsFileNode extends ViewRefFileNode<View, State> implements FileNode {
export class ResultsFileNode extends ViewRefFileNode<'results-file', View, State> implements FileNode {
constructor(
view: View,
parent: ViewNode,
@ -29,7 +29,7 @@ export class ResultsFileNode extends ViewRefFileNode implements Fil
public readonly ref2: string,
private readonly direction: 'ahead' | 'behind' | undefined,
) {
super(GitUri.fromFile(file, repoPath, ref1 || ref2), view, parent, file);
super('results-file', GitUri.fromFile(file, repoPath, ref1 || ref2), view, parent, file);
this.updateContext({ file: file });
if (this.context.storedComparisonId != null) {
@ -37,7 +37,7 @@ export class ResultsFileNode extends ViewRefFileNode implements Fil
file.path
}`;
} else {
this._uniqueId = getViewNodeId('results-file', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
}

+ 3
- 3
src/views/nodes/resultsFilesNode.ts View File

@ -32,7 +32,7 @@ export interface FilesQueryResults {
filtered?: Map<FilesQueryFilter, GitFile[]>;
}
export class ResultsFilesNode extends ViewNode<ViewsWithCommits, State> {
export class ResultsFilesNode extends ViewNode<'results-files', ViewsWithCommits, State> {
constructor(
view: ViewsWithCommits,
protected override parent: ViewNode,
@ -45,12 +45,12 @@ export class ResultsFilesNode extends ViewNode {
expand?: boolean;
} = undefined!,
) {
super(GitUri.fromRepoPath(repoPath), view, parent);
super('results-files', GitUri.fromRepoPath(repoPath), view, parent);
if (this.direction != null) {
this.updateContext({ branchStatusUpstreamType: this.direction });
}
this._uniqueId = getViewNodeId('results-files', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this._options = { expand: true, ..._options };
}

+ 3
- 3
src/views/nodes/searchResultsNode.ts View File

@ -24,7 +24,7 @@ interface SearchQueryResults {
more?(limit: number | undefined): Promise<void>;
}
export class SearchResultsNode extends ViewNode<SearchAndCompareView> implements PageableViewNode {
export class SearchResultsNode extends ViewNode<'search-results', SearchAndCompareView> implements PageableViewNode {
private _instanceId: number;
constructor(
@ -49,11 +49,11 @@ export class SearchResultsNode extends ViewNode implements
| undefined,
private _storedAt: number = 0,
) {
super(GitUri.fromRepoPath(repoPath), view, parent);
super('search-results', GitUri.fromRepoPath(repoPath), view, parent);
this._instanceId = instanceId++;
this.updateContext({ searchId: `${getSearchQueryComparisonKey(this._search)}+${this._instanceId}` });
this._uniqueId = getViewNodeId('search-results', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
// If this is a new search, save it
if (this._storedAt === 0) {

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

@ -1,14 +1,13 @@
import type { GitStashCommit } from '../../git/models/commit';
import type { GitFile } from '../../git/models/file';
import type { ViewsWithStashes } from '../viewBase';
import { CommitFileNode } from './commitFileNode';
import { CommitFileNodeBase } from './commitFileNode';
import type { ViewNode } from './viewNode';
import { ContextValues } from './viewNode';
export class StashFileNode extends CommitFileNode<ViewsWithStashes> {
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
export class StashFileNode extends CommitFileNodeBase<'stash-file', ViewsWithStashes> {
constructor(view: ViewsWithStashes, parent: ViewNode, file: GitFile, commit: GitStashCommit) {
super(view, parent, file, commit);
super('stash-file', view, parent, file, commit);
}
protected override get contextValue(): string {

+ 3
- 3
src/views/nodes/stashNode.ts View File

@ -13,17 +13,17 @@ import { StashFileNode } from './stashFileNode';
import type { ViewNode } from './viewNode';
import { ContextValues, getViewNodeId, ViewRefNode } from './viewNode';
export class StashNode extends ViewRefNode<ViewsWithStashes, GitStashReference> {
export class StashNode extends ViewRefNode<'stash', ViewsWithStashes, GitStashReference> {
constructor(
view: ViewsWithStashes,
protected override parent: ViewNode,
public readonly commit: GitStashCommit,
private readonly options?: { icon?: boolean },
) {
super(commit.getGitUri(), view, parent);
super('stash', commit.getGitUri(), view, parent);
this.updateContext({ commit: commit });
this._uniqueId = getViewNodeId('stash', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

+ 3
- 3
src/views/nodes/stashesNode.ts View File

@ -9,17 +9,17 @@ import { MessageNode } from './common';
import { StashNode } from './stashNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class StashesNode extends ViewNode<ViewsWithStashesNode> {
export class StashesNode extends ViewNode<'stashes', ViewsWithStashesNode> {
constructor(
uri: GitUri,
view: ViewsWithStashesNode,
protected override parent: ViewNode,
public readonly repo: Repository,
) {
super(uri, view, parent);
super('stashes', uri, view, parent);
this.updateContext({ repository: repo });
this._uniqueId = getViewNodeId('stashes', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

+ 2
- 2
src/views/nodes/statusFileNode.ts View File

@ -16,7 +16,7 @@ import type { FileNode } from './folderNode';
import type { ViewNode } from './viewNode';
import { ContextValues, ViewFileNode } from './viewNode';
export class StatusFileNode extends ViewFileNode<ViewsWithCommits> implements FileNode {
export class StatusFileNode extends ViewFileNode<'status-file', ViewsWithCommits> implements FileNode {
public readonly commits: GitCommit[];
private readonly _direction: 'ahead' | 'behind';
@ -55,7 +55,7 @@ export class StatusFileNode extends ViewFileNode implements Fi
}
}
super(GitUri.fromFile(file, repoPath, ref), view, parent, file);
super('status-file', GitUri.fromFile(file, repoPath, ref), view, parent, file);
this.commits = commits;

+ 3
- 3
src/views/nodes/statusFilesNode.ts View File

@ -15,7 +15,7 @@ import { FolderNode } from './folderNode';
import { StatusFileNode } from './statusFileNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class StatusFilesNode extends ViewNode<ViewsWithWorkingTree> {
export class StatusFilesNode extends ViewNode<'status-files', ViewsWithWorkingTree> {
constructor(
view: ViewsWithWorkingTree,
protected override readonly parent: ViewNode,
@ -29,9 +29,9 @@ export class StatusFilesNode extends ViewNode {
},
public readonly range: string | undefined,
) {
super(GitUri.fromRepoPath(status.repoPath), view, parent);
super('status-files', GitUri.fromRepoPath(status.repoPath), view, parent);
this._uniqueId = getViewNodeId('status-files', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

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

@ -17,7 +17,7 @@ import { insertDateMarkers } from './helpers';
import type { PageableViewNode, ViewNode } from './viewNode';
import { ContextValues, getViewNodeId, ViewRefNode } from './viewNode';
export class TagNode extends ViewRefNode<ViewsWithTags, GitTagReference> implements PageableViewNode {
export class TagNode extends ViewRefNode<'tag', ViewsWithTags, GitTagReference> implements PageableViewNode {
limit: number | undefined;
constructor(
@ -26,10 +26,10 @@ export class TagNode extends ViewRefNode impleme
public override parent: ViewNode,
public readonly tag: GitTag,
) {
super(uri, view, parent);
super('tag', uri, view, parent);
this.updateContext({ tag: tag });
this._uniqueId = getViewNodeId('tag', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this.limit = this.view.getNodeLastKnownLimit(this);
}

+ 3
- 3
src/views/nodes/tagsNode.ts View File

@ -10,17 +10,17 @@ import { MessageNode } from './common';
import { TagNode } from './tagNode';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class TagsNode extends ViewNode<ViewsWithTagsNode> {
export class TagsNode extends ViewNode<'tags', ViewsWithTagsNode> {
constructor(
uri: GitUri,
view: ViewsWithTagsNode,
protected override readonly parent: ViewNode,
public readonly repo: Repository,
) {
super(uri, view, parent);
super('tags', uri, view, parent);
this.updateContext({ repository: repo });
this._uniqueId = getViewNodeId('tags', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

+ 91
- 31
src/views/nodes/viewNode.ts View File

@ -1,5 +1,12 @@
import type { Command, Event, TreeViewVisibilityChangeEvent } from 'vscode';
import { Disposable, MarkdownString, TreeItem, TreeItemCollapsibleState } from 'vscode';
import type {
TreeViewFileNodeTypes,
TreeViewNodeTypes,
TreeViewRefFileNodeTypes,
TreeViewRefNodeTypes,
TreeViewSubscribableNodeTypes,
} from '../../constants';
import { GlyphChars } from '../../constants';
import type { RepositoriesChangeEvent } from '../../git/gitProviderService';
import type { GitUri } from '../../git/gitUri';
@ -29,7 +36,21 @@ import { is as isA, szudzikPairing } from '../../system/function';
import { getLoggableName } from '../../system/logger';
import { pad } from '../../system/string';
import type { View } from '../viewBase';
import type { BranchNode } from './branchNode';
import type { BranchTrackingStatus } from './branchTrackingStatusNode';
import type { CommitFileNode } from './commitFileNode';
import type { CommitNode } from './commitNode';
import type { FileRevisionAsCommitNode } from './fileRevisionAsCommitNode';
import type { FolderNode } from './folderNode';
import type { LineHistoryTrackerNode } from './lineHistoryTrackerNode';
import type { MergeConflictFileNode } from './mergeConflictFileNode';
import type { RepositoryNode } from './repositoryNode';
import type { ResultsFileNode } from './resultsFileNode';
import type { StashFileNode } from './stashFileNode';
import type { StashNode } from './stashNode';
import type { StatusFileNode } from './statusFileNode';
import type { TagNode } from './tagNode';
import type { UncommittedFileNode } from './UncommittedFileNode';
export const enum ContextValues {
ActiveFileHistory = 'gitlens:history:active:file',
@ -185,12 +206,21 @@ export function getViewNodeId(type: string, context: AmbientContext): string {
}
@logName<ViewNode>((c, name) => `${name}${c.id != null ? `(${c.id})` : ''}`)
export abstract class ViewNode<TView extends View = View, State extends object = any> {
export abstract class ViewNode<
Type extends TreeViewNodeTypes = TreeViewNodeTypes,
TView extends View = View,
State extends object = any,
> {
is<T extends keyof TreeViewNodesByType>(type: T): this is TreeViewNodesByType[T] {
return this.type === (type as unknown as Type);
}
protected _uniqueId!: string;
protected splatted = false;
constructor(
public readonly type: Type,
// public readonly id: string | undefined,
uri: GitUri,
public readonly view: TView,
@ -288,29 +318,22 @@ export abstract class ViewNode
this.view.nodeState.storeState(this.id, key as string, value, sticky);
}
}
export function isViewNode(node: any): node is ViewNode {
return node instanceof ViewNode;
}
export function isViewFileNode(node: any): node is ViewFileNode {
return node instanceof ViewFileNode;
}
type StateKey<T> = keyof T;
type StateValue<T, P extends StateKey<T>> = P extends keyof T ? T[P] : never;
export abstract class ViewFileNode<TView extends View = View, State extends object = any> extends ViewNode<
TView,
State
> {
export abstract class ViewFileNode<
Type extends TreeViewFileNodeTypes = TreeViewFileNodeTypes,
TView extends View = View,
State extends object = any,
> extends ViewNode<Type, TView, State> {
constructor(
type: Type,
uri: GitUri,
view: TView,
public override parent: ViewNode,
public readonly file: GitFile,
) {
super(uri, view, parent);
super(type, uri, view, parent);
}
get repoPath(): string {
@ -323,16 +346,18 @@ export abstract class ViewFileNode
}
export abstract class ViewRefNode<
Type extends TreeViewRefNodeTypes = TreeViewRefNodeTypes,
TView extends View = View,
TReference extends GitReference = GitReference,
State extends object = any,
> extends ViewNode<TView, State> {
> extends ViewNode<Type, TView, State> {
constructor(
type: Type,
uri: GitUri,
view: TView,
protected override readonly parent: ViewNode,
) {
super(uri, view, parent);
super(type, uri, view, parent);
}
abstract get ref(): TReference;
@ -346,10 +371,11 @@ export abstract class ViewRefNode<
}
}
export abstract class ViewRefFileNode<TView extends View = View, State extends object = any> extends ViewFileNode<
TView,
State
> {
export abstract class ViewRefFileNode<
Type extends TreeViewRefFileNodeTypes = TreeViewRefFileNodeTypes,
TView extends View = View,
State extends object = any,
> extends ViewFileNode<Type, TView, State> {
abstract get ref(): GitRevisionReference;
override toString(): string {
@ -368,14 +394,17 @@ export function isPageableViewNode(node: ViewNode): node is ViewNode & PageableV
return isA<ViewNode & PageableViewNode>(node, 'loadMore');
}
export abstract class SubscribeableViewNode<TView extends View = View> extends ViewNode<TView> {
export abstract class SubscribeableViewNode<
Type extends TreeViewSubscribableNodeTypes = TreeViewSubscribableNodeTypes,
TView extends View = View,
> extends ViewNode<Type, TView> {
protected disposable: Disposable;
protected subscription: Promise<Disposable | undefined> | undefined;
protected loaded: boolean = false;
constructor(uri: GitUri, view: TView, parent?: ViewNode) {
super(uri, view, parent);
constructor(type: Type, uri: GitUri, view: TView, parent?: ViewNode) {
super(type, uri, view, parent);
const disposables = [
this.view.onDidChangeVisibility(this.onVisibilityChanged, this),
@ -387,14 +416,14 @@ export abstract class SubscribeableViewNode extends V
}
const getTreeItem = this.getTreeItem;
this.getTreeItem = function (this: SubscribeableViewNode<TView>) {
this.getTreeItem = function (this: SubscribeableViewNode<Type, TView>) {
this.loaded = true;
void this.ensureSubscription();
return getTreeItem.apply(this);
};
const getChildren = this.getChildren;
this.getChildren = function (this: SubscribeableViewNode<TView>) {
this.getChildren = function (this: SubscribeableViewNode<Type, TView>) {
this.loaded = true;
void this.ensureSubscription();
return getChildren.apply(this);
@ -526,7 +555,7 @@ export abstract class SubscribeableViewNode extends V
export abstract class RepositoryFolderNode<
TView extends View = View,
TChild extends ViewNode = ViewNode,
> extends SubscribeableViewNode<TView> {
> extends SubscribeableViewNode<'repository-folder', TView> {
protected override splatted = true;
protected child: TChild | undefined;
@ -538,10 +567,10 @@ export abstract class RepositoryFolderNode<
splatted: boolean,
private readonly options?: { showBranchAndLastFetched?: boolean },
) {
super(uri, view, parent);
super('repository-folder', uri, view, parent);
this.updateContext({ repository: this.repo });
this._uniqueId = getViewNodeId('repository-folder', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this.splatted = splatted;
}
@ -704,12 +733,12 @@ export abstract class RepositoryFolderNode<
export abstract class RepositoriesSubscribeableNode<
TView extends View = View,
TChild extends ViewNode & Disposable = ViewNode & Disposable,
> extends SubscribeableViewNode<TView> {
> extends SubscribeableViewNode<'repositories', TView> {
protected override splatted = true;
protected children: TChild[] | undefined;
constructor(view: TView) {
super(unknownGitUri, view);
super('repositories', unknownGitUri, view);
}
override dispose() {
@ -797,3 +826,34 @@ export function canViewDismissNode(view: View): view is View & { dismissNode(nod
export function getNodeRepoPath(node?: ViewNode): string | undefined {
return canGetNodeRepoPath(node) ? node.repoPath : undefined;
}
type TreeViewNodesByType = {
[T in TreeViewNodeTypes]: ViewNode<T>;
} & {
['branch']: BranchNode;
['commit']: CommitNode;
['commit-file']: CommitFileNode;
['conflict-file']: MergeConflictFileNode;
['file-commit']: FileRevisionAsCommitNode;
['folder']: FolderNode;
['line-history-tracker']: LineHistoryTrackerNode;
['repository']: RepositoryNode;
['results-file']: ResultsFileNode;
['stash']: StashNode;
['stash-file']: StashFileNode;
['status-file']: StatusFileNode;
['tag']: TagNode;
['uncommitted-file']: UncommittedFileNode;
// Add more real types as needed
};
export function isViewNode(node: unknown): node is ViewNode;
export function isViewNode<T extends keyof TreeViewNodesByType>(node: unknown, type: T): node is TreeViewNodesByType[T];
export function isViewNode<T extends keyof TreeViewNodesByType>(node: unknown, type?: T): node is ViewNode {
if (node == null) return false;
return node instanceof ViewNode ? type == null || node.type === type : false;
}
export function isViewFileNode(node: unknown): node is ViewFileNode {
return node instanceof ViewFileNode;
}

+ 3
- 3
src/views/nodes/workspaceMissingRepositoryNode.ts View File

@ -10,17 +10,17 @@ import type {
import type { WorkspacesView } from '../workspacesView';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
export class WorkspaceMissingRepositoryNode extends ViewNode<WorkspacesView> {
export class WorkspaceMissingRepositoryNode extends ViewNode<'workspace-missing-repository', WorkspacesView> {
constructor(
view: WorkspacesView,
parent: ViewNode,
public readonly workspace: CloudWorkspace | LocalWorkspace,
public readonly wsRepositoryDescriptor: CloudWorkspaceRepositoryDescriptor | LocalWorkspaceRepositoryDescriptor,
) {
super(unknownGitUri, view, parent);
super('workspace-missing-repository', unknownGitUri, view, parent);
this.updateContext({ wsRepositoryDescriptor: wsRepositoryDescriptor });
this._uniqueId = getViewNodeId('missing-workspace-repository', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

+ 3
- 3
src/views/nodes/workspaceNode.ts View File

@ -12,17 +12,17 @@ import type { ViewNode } from './viewNode';
import { ContextValues, getViewNodeId, SubscribeableViewNode } from './viewNode';
import { WorkspaceMissingRepositoryNode } from './workspaceMissingRepositoryNode';
export class WorkspaceNode extends SubscribeableViewNode<WorkspacesView> {
export class WorkspaceNode extends SubscribeableViewNode<'workspace', WorkspacesView> {
constructor(
uri: GitUri,
view: WorkspacesView,
protected override parent: ViewNode,
public readonly workspace: CloudWorkspace | LocalWorkspace,
) {
super(uri, view, parent);
super('workspace', uri, view, parent);
this.updateContext({ workspace: workspace });
this._uniqueId = getViewNodeId('workspace', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override dispose() {

+ 0
- 70
src/views/nodes/workspacesViewNode.ts View File

@ -1,70 +0,0 @@
import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { gate } from '../../system/decorators/gate';
import { debug } from '../../system/decorators/log';
import type { WorkspacesView } from '../workspacesView';
import { MessageNode } from './common';
import { RepositoriesNode } from './repositoriesNode';
import { ViewNode } from './viewNode';
import { WorkspaceNode } from './workspaceNode';
export class WorkspacesViewNode extends ViewNode<WorkspacesView> {
private _children: (WorkspaceNode | MessageNode | RepositoriesNode)[] | undefined;
async getChildren(): Promise<ViewNode[]> {
if (this._children == null) {
const children: (WorkspaceNode | MessageNode | RepositoriesNode)[] = [];
const { cloudWorkspaces, cloudWorkspaceInfo, localWorkspaces, localWorkspaceInfo } =
await this.view.container.workspaces.getWorkspaces();
if (cloudWorkspaces.length || localWorkspaces.length) {
children.push(new RepositoriesNode(this.view));
for (const workspace of cloudWorkspaces) {
children.push(new WorkspaceNode(this.uri, this.view, this, workspace));
}
if (cloudWorkspaceInfo != null) {
children.push(new MessageNode(this.view, this, cloudWorkspaceInfo));
}
for (const workspace of localWorkspaces) {
children.push(new WorkspaceNode(this.uri, this.view, this, workspace));
}
if (cloudWorkspaces.length === 0 && cloudWorkspaceInfo == null) {
children.push(new MessageNode(this.view, this, 'No cloud workspaces found.'));
}
if (localWorkspaceInfo != null) {
children.push(new MessageNode(this.view, this, localWorkspaceInfo));
}
}
this._children = children;
}
return this._children;
}
getTreeItem(): TreeItem {
const item = new TreeItem('Workspaces', TreeItemCollapsibleState.Expanded);
return item;
}
@gate()
@debug()
override refresh() {
if (this._children == null) return;
if (this._children.length) {
for (const child of this._children) {
if ('dispose' in child) {
child.dispose();
}
}
}
this._children = undefined;
}
}

+ 4
- 4
src/views/nodes/worktreeNode.ts View File

@ -29,7 +29,7 @@ type State = {
pendingPullRequest: Promise<PullRequest | undefined> | undefined;
};
export class WorktreeNode extends ViewNode<ViewsWithWorktrees, State> {
export class WorktreeNode extends ViewNode<'worktree', ViewsWithWorktrees, State> {
limit: number | undefined;
private _branch: GitBranch | undefined;
@ -40,10 +40,10 @@ export class WorktreeNode extends ViewNode {
protected override readonly parent: ViewNode,
public readonly worktree: GitWorktree,
) {
super(uri, view, parent);
super('worktree', uri, view, parent);
this.updateContext({ worktree: worktree });
this._uniqueId = getViewNodeId('worktree', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
this.limit = this.view.getNodeLastKnownLimit(this);
}
@ -98,7 +98,7 @@ export class WorktreeNode extends ViewNode {
// If we found a pull request, insert it into the children cache (if loaded) and refresh the node
if (pr != null && this._children != null) {
this._children.splice(
this._children[0] instanceof CompareBranchNode ? 1 : 0,
this._children[0].type === 'compare-branch' ? 1 : 0,
0,
new PullRequestNode(this.view, this, pr, branch),
);

+ 3
- 3
src/views/nodes/worktreesNode.ts View File

@ -10,7 +10,7 @@ import { MessageNode } from './common';
import { ContextValues, getViewNodeId, ViewNode } from './viewNode';
import { WorktreeNode } from './worktreeNode';
export class WorktreesNode extends ViewNode<ViewsWithWorktreesNode> {
export class WorktreesNode extends ViewNode<'worktrees', ViewsWithWorktreesNode> {
private _children: WorktreeNode[] | undefined;
constructor(
@ -19,10 +19,10 @@ export class WorktreesNode extends ViewNode {
protected override readonly parent: ViewNode,
public readonly repo: Repository,
) {
super(uri, view, parent);
super('worktrees', uri, view, parent);
this.updateContext({ repository: repo });
this._uniqueId = getViewNodeId('worktrees', this.context);
this._uniqueId = getViewNodeId(this.type, this.context);
}
override get id(): string {

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

@ -27,12 +27,12 @@ import { ContextValues, RepositoryFolderNode, ViewNode } from './nodes/viewNode'
import { ViewBase } from './viewBase';
import { registerViewCommand } from './viewCommands';
export class SearchAndCompareViewNode extends ViewNode<SearchAndCompareView> {
export class SearchAndCompareViewNode extends ViewNode<'search-compare', SearchAndCompareView> {
protected override splatted = true;
private comparePicker: ComparePickerNode | undefined;
constructor(view: SearchAndCompareView) {
super(unknownGitUri, view);
super('search-compare', unknownGitUri, view);
}
private _children: (ComparePickerNode | CompareResultsNode | SearchResultsNode)[] | undefined;

+ 75
- 6
src/views/workspacesView.ts View File

@ -1,22 +1,91 @@
import type { CancellationToken, Disposable } from 'vscode';
import { env, ProgressLocation, Uri, window } from 'vscode';
import type { RepositoriesViewConfig } from '../config';
import { env, ProgressLocation, TreeItem, TreeItemCollapsibleState, Uri, window } from 'vscode';
import type { WorkspacesViewConfig } from '../config';
import { Commands } from '../constants';
import type { Container } from '../container';
import { unknownGitUri } from '../git/gitUri';
import type { Repository } from '../git/models/repository';
import { ensurePlusFeaturesEnabled } from '../plus/subscription/utils';
import { executeCommand } from '../system/command';
import { gate } from '../system/decorators/gate';
import { debug } from '../system/decorators/log';
import { openWorkspace } from '../system/utils';
import type { RepositoriesNode } from './nodes/repositoriesNode';
import { MessageNode } from './nodes/common';
import { RepositoriesNode } from './nodes/repositoriesNode';
import { RepositoryNode } from './nodes/repositoryNode';
import { ViewNode } from './nodes/viewNode';
import type { WorkspaceMissingRepositoryNode } from './nodes/workspaceMissingRepositoryNode';
import { WorkspaceNode } from './nodes/workspaceNode';
import { WorkspacesViewNode } from './nodes/workspacesViewNode';
import { ViewBase } from './viewBase';
import { registerViewCommand } from './viewCommands';
export class WorkspacesView extends ViewBase<'workspaces', WorkspacesViewNode, RepositoriesViewConfig> {
export class WorkspacesViewNode extends ViewNode<'workspaces-view', WorkspacesView> {
constructor(view: WorkspacesView) {
super('workspaces-view', unknownGitUri, view);
}
private _children: (WorkspaceNode | MessageNode | RepositoriesNode)[] | undefined;
async getChildren(): Promise<ViewNode[]> {
if (this._children == null) {
const children: (WorkspaceNode | MessageNode | RepositoriesNode)[] = [];
const { cloudWorkspaces, cloudWorkspaceInfo, localWorkspaces, localWorkspaceInfo } =
await this.view.container.workspaces.getWorkspaces();
if (cloudWorkspaces.length || localWorkspaces.length) {
children.push(new RepositoriesNode(this.view));
for (const workspace of cloudWorkspaces) {
children.push(new WorkspaceNode(this.uri, this.view, this, workspace));
}
if (cloudWorkspaceInfo != null) {
children.push(new MessageNode(this.view, this, cloudWorkspaceInfo));
}
for (const workspace of localWorkspaces) {
children.push(new WorkspaceNode(this.uri, this.view, this, workspace));
}
if (cloudWorkspaces.length === 0 && cloudWorkspaceInfo == null) {
children.push(new MessageNode(this.view, this, 'No cloud workspaces found.'));
}
if (localWorkspaceInfo != null) {
children.push(new MessageNode(this.view, this, localWorkspaceInfo));
}
}
this._children = children;
}
return this._children;
}
getTreeItem(): TreeItem {
const item = new TreeItem('Workspaces', TreeItemCollapsibleState.Expanded);
return item;
}
@gate()
@debug()
override refresh() {
if (this._children == null) return;
if (this._children.length) {
for (const child of this._children) {
if ('dispose' in child) {
child.dispose();
}
}
}
this._children = undefined;
}
}
export class WorkspacesView extends ViewBase<'workspaces', WorkspacesViewNode, WorkspacesViewConfig> {
protected readonly configKey = 'repositories';
private _disposable: Disposable | undefined;
@ -37,7 +106,7 @@ export class WorkspacesView extends ViewBase<'workspaces', WorkspacesViewNode, R
}
protected getRoot() {
return new WorkspacesViewNode(unknownGitUri, this);
return new WorkspacesViewNode(this);
}
override async show(options?: { preserveFocus?: boolean | undefined }): Promise<void> {

Loading…
Cancel
Save