From c1f8dc84972bd443983b4106c5dc8876e1aadc3f Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Mon, 11 Nov 2024 03:37:01 -0500 Subject: [PATCH 1/3] Moves view description to ViewBase Fixes focus issue when attaching/detaching views --- src/views/branchesView.ts | 4 ++-- src/views/commitsView.ts | 2 +- src/views/contributorsView.ts | 4 ++-- .../abstract/repositoriesSubscribeableNode.ts | 6 ----- src/views/remotesView.ts | 4 ++-- src/views/scmGroupedView.ts | 24 ++++++++++--------- src/views/stashesView.ts | 4 ++-- src/views/tagsView.ts | 4 ++-- src/views/viewBase.ts | 11 ++++++--- src/views/views.ts | 8 +++---- src/views/worktreesView.ts | 18 +++++--------- 11 files changed, 42 insertions(+), 47 deletions(-) diff --git a/src/views/branchesView.ts b/src/views/branchesView.ts index cc8107e673f0f..886601096349e 100644 --- a/src/views/branchesView.ts +++ b/src/views/branchesView.ts @@ -48,7 +48,7 @@ export class BranchesRepositoryNode extends RepositoryFolderNode { async getChildren(): Promise { - this.view.description = this.getViewDescription(); + this.view.description = this.view.getViewDescription(); this.view.message = undefined; if (this.children == null) { @@ -91,7 +91,7 @@ export class BranchesViewNode extends RepositoriesSubscribeableNode { async getChildren(): Promise { if (this.children == null) { - this.view.description = this.getViewDescription(); + this.view.description = this.view.getViewDescription(); this.view.message = undefined; const repositories = this.view.container.git.openRepositories; diff --git a/src/views/contributorsView.ts b/src/views/contributorsView.ts index 585b917ee62a5..7c412aadba4eb 100644 --- a/src/views/contributorsView.ts +++ b/src/views/contributorsView.ts @@ -53,7 +53,7 @@ export class ContributorsRepositoryNode extends RepositoryFolderNode { async getChildren(): Promise { - this.view.description = this.getViewDescription(); + this.view.description = this.view.getViewDescription(); this.view.message = undefined; if (this.children == null) { @@ -106,7 +106,7 @@ export class ContributorsViewNode extends RepositoriesSubscribeableNode { return Disposable.from( diff --git a/src/views/remotesView.ts b/src/views/remotesView.ts index 7b5bb4a48052e..39295a3bd51d7 100644 --- a/src/views/remotesView.ts +++ b/src/views/remotesView.ts @@ -48,7 +48,7 @@ export class RemotesRepositoryNode extends RepositoryFolderNode { async getChildren(): Promise { - this.view.description = this.getViewDescription(); + this.view.description = this.view.getViewDescription(); this.view.message = undefined; if (this.children == null) { @@ -83,7 +83,7 @@ export class RemotesViewNode extends RepositoriesSubscribeableNode this.setView('branches')), - registerCommand('gitlens.views.scm.grouped.commits', () => this.setView('commits')), - registerCommand('gitlens.views.scm.grouped.contributors', () => this.setView('contributors')), - registerCommand('gitlens.views.scm.grouped.remotes', () => this.setView('remotes')), - registerCommand('gitlens.views.scm.grouped.repositories', () => this.setView('repositories')), - registerCommand('gitlens.views.scm.grouped.searchAndCompare', () => this.setView('searchAndCompare')), - registerCommand('gitlens.views.scm.grouped.stashes', () => this.setView('stashes')), - registerCommand('gitlens.views.scm.grouped.tags', () => this.setView('tags')), - registerCommand('gitlens.views.scm.grouped.worktrees', () => this.setView('worktrees')), + registerCommand('gitlens.views.scm.grouped.branches', () => this.setView('branches', true)), + registerCommand('gitlens.views.scm.grouped.commits', () => this.setView('commits', true)), + registerCommand('gitlens.views.scm.grouped.contributors', () => this.setView('contributors', true)), + registerCommand('gitlens.views.scm.grouped.remotes', () => this.setView('remotes', true)), + registerCommand('gitlens.views.scm.grouped.repositories', () => this.setView('repositories', true)), + registerCommand('gitlens.views.scm.grouped.searchAndCompare', () => this.setView('searchAndCompare', true)), + registerCommand('gitlens.views.scm.grouped.stashes', () => this.setView('stashes', true)), + registerCommand('gitlens.views.scm.grouped.tags', () => this.setView('tags', true)), + registerCommand('gitlens.views.scm.grouped.worktrees', () => this.setView('worktrees', true)), ); this._view = this.setView(this.views.lastSelectedScmGroupedView!); @@ -49,7 +49,7 @@ export class ScmGroupedView implements Disposable { this._view?.dispose(); } - setView(type: T): TreeViewByType[T] { + setView(type: T, focus?: boolean): TreeViewByType[T] { if (!this.views.scmGroupedViews.has(type)) { type = first(this.views.scmGroupedViews) as T; } @@ -61,7 +61,9 @@ export class ScmGroupedView implements Disposable { this._view?.dispose(); this._view = this.getView(type); - void this._view.show({ preserveFocus: false }); + if (focus) { + void this._view.show({ preserveFocus: false }); + } this.views.lastSelectedScmGroupedView = type; return this._view as TreeViewByType[T]; diff --git a/src/views/stashesView.ts b/src/views/stashesView.ts index 41460495cff5a..c0eaa2b44f7ad 100644 --- a/src/views/stashesView.ts +++ b/src/views/stashesView.ts @@ -34,7 +34,7 @@ export class StashesRepositoryNode extends RepositoryFolderNode { async getChildren(): Promise { - this.view.description = this.getViewDescription(); + this.view.description = this.view.getViewDescription(); this.view.message = undefined; if (this.children == null) { @@ -69,7 +69,7 @@ export class StashesViewNode extends RepositoriesSubscribeableNode export class TagsViewNode extends RepositoriesSubscribeableNode { async getChildren(): Promise { - this.view.description = this.getViewDescription(); + this.view.description = this.view.getViewDescription(); this.view.message = undefined; if (this.children == null) { @@ -70,7 +70,7 @@ export class TagsViewNode extends RepositoriesSubscribeableNode { return node.resolveTreeItem?.(item, token) ?? item; } diff --git a/src/views/views.ts b/src/views/views.ts index 4f4336dffc3df..cc0267e622852 100644 --- a/src/views/views.ts +++ b/src/views/views.ts @@ -244,20 +244,20 @@ export class Views implements Disposable { private async toggleScmViewGrouping(type: GroupableTreeViewTypes, grouped: boolean) { if (grouped) { if (!this._scmGroupedViews.has(type)) { - this.lastSelectedScmGroupedView = type; this._scmGroupedViews.add(type); + this.lastSelectedScmGroupedView = type; } } else if (this._scmGroupedViews.has(type)) { + this._scmGroupedViews.delete(type); if (type === this.lastSelectedScmGroupedView) { - this.lastSelectedScmGroupedView = undefined; + this.lastSelectedScmGroupedView = first(this._scmGroupedViews); } - this._scmGroupedViews.delete(type); } await updateScmGroupedViewsInConfig(this._scmGroupedViews); // Show the view after the configuration change has been applied - setTimeout(() => executeCoreCommand(`gitlens.views.${type}.focus`), 1); + setTimeout(() => executeCoreCommand(`gitlens.views.${grouped ? 'scm.grouped' : type}.focus`), 1); } private updateScmGroupedViewsRegistration() { diff --git a/src/views/worktreesView.ts b/src/views/worktreesView.ts index 1ffb457ad6c23..5160d7d71c57d 100644 --- a/src/views/worktreesView.ts +++ b/src/views/worktreesView.ts @@ -41,13 +41,8 @@ export class WorktreesRepositoryNode extends RepositoryFolderNode { - protected override getViewDescription(count?: number): string { - const description = super.getViewDescription(count); - return description ? `${description} \u00a0\u2022\u00a0 ${proBadge}` : proBadge; - } - async getChildren(): Promise { - this.view.description = this.getViewDescription(); + this.view.description = this.view.getViewDescription(); this.view.message = undefined; if (this.children == null) { @@ -84,7 +79,7 @@ export class WorktreesViewNode extends RepositoriesSubscribeableNode Date: Wed, 6 Nov 2024 13:41:23 -0700 Subject: [PATCH 2/3] Takes Launchpad View out of Experimental Adds gating states where needed --- package.json | 60 ++++++++++++++++++++++++++++++-------- src/views/launchpadView.ts | 41 ++++++++++++-------------- 2 files changed, 66 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index 65fa5b623212c..4035b31634cf0 100644 --- a/package.json +++ b/package.json @@ -1658,16 +1658,9 @@ }, { "id": "launchpad-view", - "title": "Launchpad View (ᴇxᴘᴇʀɪᴍᴇɴᴛᴀʟ)", + "title": "Launchpad View (ᴘʀᴏ)", "order": 101, "properties": { - "gitlens.views.launchpad.enabled": { - "type": "boolean", - "default": false, - "markdownDescription": "(Experimental) Specifies whether to enable an experimental _Launchpad_ view", - "scope": "window", - "order": 10 - }, "gitlens.views.launchpad.files.layout": { "type": "string", "default": "auto", @@ -19077,13 +19070,57 @@ }, { "view": "gitlens.views.launchpad", - "contents": "[Launchpad](command:gitlens.views.launchpad.info \"Learn about Launchpad\") — organizes your pull requests into actionable groups to help you focus and keep your team unblocked.", - "when": "config.gitlens.views.launchpad.enabled" + "contents": "[Launchpad](command:gitlens.views.launchpad.info \"Learn about Launchpad\") — organizes your pull requests into actionable groups to help you focus and keep your team unblocked." }, { "view": "gitlens.views.launchpad", "contents": "[Connect an Integration...](command:gitlens.showLaunchpad?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nAllows Launchpad to organize your pull requests into actionable groups and keep your team unblocked.", - "when": "config.gitlens.views.launchpad.enabled && gitlens:launchpad:connect" + "when": "gitlens:launchpad:connect" + }, + { + "view": "gitlens.views.launchpad", + "contents": "[Resend Verification Email](command:gitlens.plus.resendVerification?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nYou must verify your email before you can continue or [recheck Status](command:gitlens.plus.validate?%7B%22source%22%3A%22launchpad-view%22%7D).", + "when": "!gitlens:launchpad:connect && gitlens:plus:state == -1" + }, + { + "view": "gitlens.views.launchpad", + "contents": "[Continue](command:gitlens.plus.startPreviewTrial?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nContinuing gives you 3 days to preview Launchpad and other local Pro features for 3 days. [Start 7-day Pro trial](command:gitlens.plus.signUp?%7B%22source%22%3A%22launchpad-view%22%7D) or [sign in](command:gitlens.plus.login?%7B%22source%22%3A%22launchpad-view%22%7D) for full access to Pro features.", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 0" + }, + { + "view": "gitlens.views.launchpad", + "contents": "[Start Pro Trial](command:gitlens.plus.signUp?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nStart your free 7-day Pro trial to try Launchpad and other Pro features, or [sign in](command:gitlens.plus.login?%7B%22source%22%3A%22launchpad-view%22%7D).", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 2" + }, + { + "view": "gitlens.views.launchpad", + "contents": "[Upgrade to Pro](command:gitlens.plus.upgrade?%7B%22source%22%3A%22launchpad-view%22%7D)", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 4" + }, + { + "view": "gitlens.views.launchpad", + "contents": "Limited-time sale: Save 33% or more on your 1st seat of Pro.", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 4 && (gitlens:promo == pro50 || !gitlens:promo)" + }, + { + "view": "gitlens.views.launchpad", + "contents": "Limited-time sale: Save up to 80% on GitLens Pro", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 4 && gitlens:promo == devexdays" + }, + { + "view": "gitlens.views.launchpad", + "contents": "Your Pro trial has ended. Please upgrade for full access to Launchpad and other Pro features.", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 4" + }, + { + "view": "gitlens.views.launchpad", + "contents": "[Continue](command:gitlens.plus.reactivateProTrial?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nReactivate your Pro trial and experience Launchpad and all the new Pro features — free for another 7 days!", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 5" + }, + { + "view": "gitlens.views.launchpad", + "contents": "Pro feature — requires a paid plan for use on privately-hosted repos.", + "when": "!gitlens:launchpad:connect" }, { "view": "gitlens.views.workspaces", @@ -19226,7 +19263,6 @@ { "id": "gitlens.views.launchpad", "name": "Launchpad", - "when": "config.gitlens.views.launchpad.enabled", "contextualTitle": "GitLens", "icon": "$(rocket)", "initialSize": 2, diff --git a/src/views/launchpadView.ts b/src/views/launchpadView.ts index fef14afaf9caa..8c3125bc03841 100644 --- a/src/views/launchpadView.ts +++ b/src/views/launchpadView.ts @@ -1,12 +1,14 @@ -import type { ConfigurationChangeEvent, MessageItem, TreeViewVisibilityChangeEvent } from 'vscode'; +import type { ConfigurationChangeEvent, TreeViewVisibilityChangeEvent } from 'vscode'; import { Disposable, ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, window } from 'vscode'; import type { OpenWalkthroughCommandArgs } from '../commands/walkthroughs'; import type { LaunchpadViewConfig, ViewFilesLayout } from '../config'; -import { experimentalBadge } from '../constants'; import { Commands } from '../constants.commands'; import type { Container } from '../container'; import { AuthenticationRequiredError } from '../errors'; +import { PlusFeatures } from '../features'; import { GitUri, unknownGitUri } from '../git/gitUri'; +import type { SubscriptionChangeEvent } from '../plus/gk/account/subscriptionService'; +import { ensurePlusFeaturesEnabled } from '../plus/gk/utils'; import type { LaunchpadCommandArgs } from '../plus/launchpad/launchpad'; import type { LaunchpadGroup, LaunchpadItem } from '../plus/launchpad/launchpadProvider'; import { @@ -125,7 +127,10 @@ export class LaunchpadViewNode extends CacheableChildrenViewNode< constructor(view: LaunchpadView) { super('launchpad', unknownGitUri, view); - this.disposable = Disposable.from(this.view.container.launchpad.onDidChange(this.refresh, this)); + this.disposable = Disposable.from( + this.view.container.launchpad.onDidChange(this.refresh, this), + this.view.container.subscription.onDidChange(this.onSubscriptionChanged, this), + ); } override dispose() { @@ -133,6 +138,12 @@ export class LaunchpadViewNode extends CacheableChildrenViewNode< super.dispose(); } + private onSubscriptionChanged(e: SubscriptionChangeEvent) { + if (e.current.plan !== e.previous.plan) { + void this.triggerChange(true); + } + } + override refresh() { if (this.children == null) return; @@ -142,6 +153,9 @@ export class LaunchpadViewNode extends CacheableChildrenViewNode< async getChildren(): Promise<(GroupingNode | LaunchpadItemNode)[]> { if (this.children == null) { + const access = await this.view.container.git.access(PlusFeatures.Launchpad); + if (!access.allowed) return []; + const children: (GroupingNode | LaunchpadItemNode)[] = []; this.view.message = undefined; @@ -208,8 +222,6 @@ export class LaunchpadView extends ViewBase<'launchpad', LaunchpadViewNode, Laun constructor(container: Container) { super(container, 'launchpad', 'Launchpad', 'launchpadView'); - - this.description = experimentalBadge; } override dispose() { @@ -233,24 +245,7 @@ export class LaunchpadView extends ViewBase<'launchpad', LaunchpadViewNode, Laun } override async show(options?: { preserveFocus?: boolean | undefined }): Promise { - if (!configuration.get('views.launchpad.enabled')) { - const confirm: MessageItem = { title: 'Enable' }; - const cancel: MessageItem = { title: 'Cancel', isCloseAffordance: true }; - const result = await window.showInformationMessage( - 'Would you like to try the new experimental Launchpad view?', - { - modal: true, - detail: 'Launchpad organizes your pull requests into actionable groups to help you focus and keep your team unblocked.', - }, - confirm, - cancel, - ); - - if (result !== confirm) return; - - await configuration.updateEffective('views.launchpad.enabled', true); - } - + if (!(await ensurePlusFeaturesEnabled())) return; return super.show(options); } From 7962662487b8dd6131fbb1de92dda2745ef71735 Mon Sep 17 00:00:00 2001 From: Ramin Tadayon Date: Thu, 7 Nov 2024 08:12:21 -0700 Subject: [PATCH 3/3] Adds grouping support for launchpad view --- images/icons/launchpad-view-filled.svg | 1 + images/icons/launchpad-view.svg | 1 + images/icons/template/mapping.json | 4 +- package.json | 236 ++++++++++++++++-- src/constants.views.ts | 1 + src/views/launchpadView.ts | 17 +- src/views/scmGroupedView.ts | 4 + src/views/views.ts | 27 +- .../apps/commitDetails/commitDetails.html | 2 +- src/webviews/apps/home/home.html | 2 +- src/webviews/apps/plus/graph/graph.html | 2 +- .../apps/plus/patchDetails/patchDetails.html | 2 +- src/webviews/apps/plus/timeline/timeline.html | 2 +- src/webviews/apps/shared/glicons.scss | 8 +- 14 files changed, 276 insertions(+), 33 deletions(-) create mode 100644 images/icons/launchpad-view-filled.svg create mode 100644 images/icons/launchpad-view.svg diff --git a/images/icons/launchpad-view-filled.svg b/images/icons/launchpad-view-filled.svg new file mode 100644 index 0000000000000..9d3fb65ab6576 --- /dev/null +++ b/images/icons/launchpad-view-filled.svg @@ -0,0 +1 @@ + diff --git a/images/icons/launchpad-view.svg b/images/icons/launchpad-view.svg new file mode 100644 index 0000000000000..6ccdf36c57826 --- /dev/null +++ b/images/icons/launchpad-view.svg @@ -0,0 +1 @@ + diff --git a/images/icons/template/mapping.json b/images/icons/template/mapping.json index 5d0006dfb4ca2..59174b8aa8e57 100644 --- a/images/icons/template/mapping.json +++ b/images/icons/template/mapping.json @@ -62,5 +62,7 @@ "search-view-filled": 61755, "stashes-view-filled": 61756, "tags-view-filled": 61757, - "worktrees-view-filled": 61758 + "worktrees-view-filled": 61758, + "launchpad-view": 61759, + "launchpad-view-filled": 61760 } \ No newline at end of file diff --git a/package.json b/package.json index 4035b31634cf0..a56d3e1aeb5e4 100644 --- a/package.json +++ b/package.json @@ -1427,7 +1427,8 @@ "worktrees", "contributors", "repositories", - "searchAndCompare" + "searchAndCompare", + "launchpad" ], "enumDescriptions": [ "Commits view", @@ -1438,7 +1439,8 @@ "Worktrees view", "Contributors view", "Repositories view", - "Search & Compare view" + "Search & Compare view", + "Launchpad view" ], "markdownDescription": "Specifies the default view to show when the _GitLens_ view is opened", "scope": "window", @@ -1454,8 +1456,9 @@ "tags": true, "worktrees": true, "contributors": true, - "repositories": true, - "searchAndCompare": true + "repositories": false, + "searchAndCompare": true, + "launchpad": false }, "properties": { "commits": { @@ -1495,13 +1498,18 @@ }, "repositories": { "type": "boolean", - "default": true, + "default": false, "description": "Group the Repositories view" }, "searchAndCompare": { "type": "boolean", "default": true, "description": "Group the Search & Compare view" + }, + "launchpad": { + "type": "boolean", + "default": false, + "description": "Group the Launchpad view" } }, "additionalProperties": false, @@ -8259,6 +8267,24 @@ "command": "gitlens.views.scm.grouped.contributors.setAsDefault", "title": "Set as Default View" }, + { + "command": "gitlens.views.scm.grouped.launchpad", + "title": "Launchpad", + "icon": "$(gitlens-launchpad-view)" + }, + { + "command": "gitlens.views.scm.grouped.launchpad.detach", + "title": "Detach Launchpad View", + "icon": "$(gitlens-launchpad-view)" + }, + { + "command": "gitlens.views.scm.grouped.launchpad.regroup", + "title": "Regroup Launchpad View" + }, + { + "command": "gitlens.views.scm.grouped.launchpad.setAsDefault", + "title": "Set as Default View" + }, { "command": "gitlens.views.scm.grouped.remotes", "title": "Remotes", @@ -8384,6 +8410,12 @@ "category": "GitLens", "icon": "$(info)" }, + { + "command": "gitlens.views.launchpad.regroup", + "title": "Regroup with GitLens View", + "category": "GitLens", + "icon": "$(close)" + }, { "command": "gitlens.views.launchpad.refresh", "title": "Refresh", @@ -10156,6 +10188,20 @@ "fontPath": "dist/glicons.woff2", "fontCharacter": "\\f13e" } + }, + "gitlens-launchpad-view": { + "description": "launchpad-view icon", + "default": { + "fontPath": "dist/glicons.woff2", + "fontCharacter": "\\f13f" + } + }, + "gitlens-launchpad-view-filled": { + "description": "launchpad-view-filled icon", + "default": { + "fontPath": "dist/glicons.woff2", + "fontCharacter": "\\f140" + } } }, "menus": { @@ -11932,6 +11978,22 @@ "command": "gitlens.views.scm.grouped.contributors.setAsDefault", "when": "false" }, + { + "command": "gitlens.views.scm.grouped.launchpad", + "when": "false" + }, + { + "command": "gitlens.views.scm.grouped.launchpad.detach", + "when": "false" + }, + { + "command": "gitlens.views.scm.grouped.launchpad.regroup", + "when": "false" + }, + { + "command": "gitlens.views.scm.grouped.launchpad.setAsDefault", + "when": "false" + }, { "command": "gitlens.views.scm.grouped.remotes", "when": "false" @@ -12040,6 +12102,10 @@ "command": "gitlens.views.launchpad.info", "when": "false" }, + { + "command": "gitlens.views.launchpad.regroup", + "when": "false" + }, { "command": "gitlens.views.launchpad.refresh", "when": "false" @@ -14038,6 +14104,22 @@ "when": "view == gitlens.views.scm.grouped && !config.gitlens.views.scm.grouped.views.searchAndCompare", "group": "2_gitlens@9" }, + { + "command": "gitlens.views.scm.grouped.launchpad", + "when": "view == gitlens.views.scm.grouped && config.gitlens.views.scm.grouped.views.launchpad && gitlens:views:scm:grouped:view != launchpad", + "group": "navigation@10", + "alt": "gitlens.views.scm.grouped.launchpad.detach" + }, + { + "submenu": "gitlens/views/grouped/launchpad", + "when": "view == gitlens.views.scm.grouped && config.gitlens.views.scm.grouped.views.launchpad && gitlens:views:scm:grouped:view == launchpad", + "group": "navigation@10" + }, + { + "command": "gitlens.views.scm.grouped.launchpad.regroup", + "when": "view == gitlens.views.scm.grouped && !config.gitlens.views.scm.grouped.views.launchpad", + "group": "2_gitlens@10" + }, { "command": "gitlens.views.scm.grouped.refresh", "when": "view == gitlens.views.scm.grouped", @@ -14051,6 +14133,11 @@ { "command": "gitlens.views.launchpad.refresh", "when": "view == gitlens.views.launchpad", + "group": "navigation@98" + }, + { + "command": "gitlens.views.launchpad.regroup", + "when": "view == gitlens.views.launchpad && config.gitlens.views.scm.grouped.enabled", "group": "navigation@99" }, { @@ -17767,6 +17854,23 @@ "group": "2_gitlens_actions@1" } ], + "gitlens/views/grouped/launchpad": [ + { + "command": "gitlens.views.scm.grouped.launchpad.detach", + "when": "gitlens:views:scm:grouped:view == launchpad", + "group": "2_gitlens@1" + }, + { + "command": "gitlens.views.scm.grouped.launchpad.setAsDefault", + "when": "gitlens:views:scm:grouped:view == launchpad && config.gitlens.views.scm.grouped.default != launchpad", + "group": "2_gitlens@2" + }, + { + "submenu": "gitlens/views/grouped/more", + "when": "gitlens:views:scm:grouped:view == launchpad", + "group": "2_gitlens@3" + } + ], "gitlens/views/grouped/remotes": [ { "command": "gitlens.views.scm.grouped.remotes.detach", @@ -18115,6 +18219,36 @@ "when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == contributors", "group": "9_gitlens@1" }, + { + "command": "gitlens.views.launchpad.setFilesLayoutToAuto", + "when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == launchpad && config.gitlens.views.launchpad.files.layout == tree", + "group": "3_gitlens@1" + }, + { + "command": "gitlens.views.launchpad.setFilesLayoutToList", + "when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == launchpad && config.gitlens.views.launchpad.files.layout == auto", + "group": "3_gitlens@1" + }, + { + "command": "gitlens.views.launchpad.setFilesLayoutToTree", + "when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == launchpad && config.gitlens.views.launchpad.files.layout == list", + "group": "3_gitlens@1" + }, + { + "command": "gitlens.views.launchpad.setShowAvatarsOn", + "when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == launchpad && !config.gitlens.views.launchpad.avatars", + "group": "5_gitlens@0" + }, + { + "command": "gitlens.views.launchpad.setShowAvatarsOff", + "when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == launchpad && config.gitlens.views.launchpad.avatars", + "group": "5_gitlens@0" + }, + { + "command": "gitlens.views.launchpad.info", + "when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == launchpad", + "group": "8_info@1" + }, { "command": "gitlens.views.remotes.setLayoutToList", "when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == remotes && config.gitlens.views.remotes.branches.layout == tree", @@ -18436,6 +18570,11 @@ "label": "Contributors", "icon": "$(gitlens-contributors-view-filled)" }, + { + "id": "gitlens/views/grouped/launchpad", + "label": "Launchpad", + "icon": "$(gitlens-launchpad-view-filled)" + }, { "id": "gitlens/views/grouped/remotes", "label": "Remotes", @@ -18927,47 +19066,52 @@ { "command": "gitlens.views.scm.grouped.commits", "key": "1", - "when": "focusedView == gitlens.views.scm.grouped" + "when": "focusedView == gitlens.views.scm.grouped && config.gitlens.views.scm.grouped.views.commits" }, { "command": "gitlens.views.scm.grouped.branches", "key": "2", - "when": "focusedView == gitlens.views.scm.grouped" + "when": "focusedView == gitlens.views.scm.grouped && config.gitlens.views.scm.grouped.views.branches" }, { "command": "gitlens.views.scm.grouped.remotes", "key": "3", - "when": "focusedView == gitlens.views.scm.grouped" + "when": "focusedView == gitlens.views.scm.grouped && config.gitlens.views.scm.grouped.views.remotes" }, { "command": "gitlens.views.scm.grouped.stashes", "key": "4", - "when": "focusedView == gitlens.views.scm.grouped" + "when": "focusedView == gitlens.views.scm.grouped && config.gitlens.views.scm.grouped.views.stashes" }, { "command": "gitlens.views.scm.grouped.tags", "key": "5", - "when": "focusedView == gitlens.views.scm.grouped" + "when": "focusedView == gitlens.views.scm.grouped && config.gitlens.views.scm.grouped.views.tags" }, { "command": "gitlens.views.scm.grouped.worktrees", "key": "6", - "when": "focusedView == gitlens.views.scm.grouped" + "when": "focusedView == gitlens.views.scm.grouped && config.gitlens.views.scm.grouped.views.worktrees" }, { "command": "gitlens.views.scm.grouped.contributors", "key": "7", - "when": "focusedView == gitlens.views.scm.grouped" + "when": "focusedView == gitlens.views.scm.grouped && config.gitlens.views.scm.grouped.views.contributors" }, { "command": "gitlens.views.scm.grouped.repositories", "key": "8", - "when": "focusedView == gitlens.views.scm.grouped" + "when": "focusedView == gitlens.views.scm.grouped && config.gitlens.views.scm.grouped.views.repositories" }, { "command": "gitlens.views.scm.grouped.searchAndCompare", "key": "9", - "when": "focusedView == gitlens.views.scm.grouped" + "when": "focusedView == gitlens.views.scm.grouped && config.gitlens.views.scm.grouped.views.searchAndCompare" + }, + { + "command": "gitlens.views.scm.grouped.launchpad", + "key": "0", + "when": "focusedView == gitlens.views.scm.grouped && config.gitlens.views.scm.grouped.views.launchpad" } ], "customEditors": [ @@ -19072,56 +19216,111 @@ "view": "gitlens.views.launchpad", "contents": "[Launchpad](command:gitlens.views.launchpad.info \"Learn about Launchpad\") — organizes your pull requests into actionable groups to help you focus and keep your team unblocked." }, + { + "view": "gitlens.views.scm.grouped", + "contents": "[Launchpad](command:gitlens.views.launchpad.info \"Learn about Launchpad\") — organizes your pull requests into actionable groups to help you focus and keep your team unblocked.", + "when": "gitlens:views:scm:grouped:view == launchpad" + }, { "view": "gitlens.views.launchpad", "contents": "[Connect an Integration...](command:gitlens.showLaunchpad?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nAllows Launchpad to organize your pull requests into actionable groups and keep your team unblocked.", "when": "gitlens:launchpad:connect" }, + { + "view": "gitlens.views.scm.grouped", + "contents": "[Connect an Integration...](command:gitlens.showLaunchpad?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nAllows Launchpad to organize your pull requests into actionable groups and keep your team unblocked.", + "when": "gitlens:launchpad:connect && gitlens:views:scm:grouped:view == launchpad" + }, { "view": "gitlens.views.launchpad", "contents": "[Resend Verification Email](command:gitlens.plus.resendVerification?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nYou must verify your email before you can continue or [recheck Status](command:gitlens.plus.validate?%7B%22source%22%3A%22launchpad-view%22%7D).", "when": "!gitlens:launchpad:connect && gitlens:plus:state == -1" }, + { + "view": "gitlens.views.scm.grouped", + "contents": "[Resend Verification Email](command:gitlens.plus.resendVerification?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nYou must verify your email before you can continue or [recheck Status](command:gitlens.plus.validate?%7B%22source%22%3A%22launchpad-view%22%7D).", + "when": "!gitlens:launchpad:connect && gitlens:plus:state == -1 && gitlens:views:scm:grouped:view == launchpad" + }, { "view": "gitlens.views.launchpad", "contents": "[Continue](command:gitlens.plus.startPreviewTrial?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nContinuing gives you 3 days to preview Launchpad and other local Pro features for 3 days. [Start 7-day Pro trial](command:gitlens.plus.signUp?%7B%22source%22%3A%22launchpad-view%22%7D) or [sign in](command:gitlens.plus.login?%7B%22source%22%3A%22launchpad-view%22%7D) for full access to Pro features.", "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 0" }, + { + "view": "gitlens.views.scm.grouped", + "contents": "[Continue](command:gitlens.plus.startPreviewTrial?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nContinuing gives you 3 days to preview Launchpad and other local Pro features for 3 days. [Start 7-day Pro trial](command:gitlens.plus.signUp?%7B%22source%22%3A%22launchpad-view%22%7D) or [sign in](command:gitlens.plus.login?%7B%22source%22%3A%22launchpad-view%22%7D) for full access to Pro features.", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 0 && gitlens:views:scm:grouped:view == launchpad" + }, { "view": "gitlens.views.launchpad", "contents": "[Start Pro Trial](command:gitlens.plus.signUp?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nStart your free 7-day Pro trial to try Launchpad and other Pro features, or [sign in](command:gitlens.plus.login?%7B%22source%22%3A%22launchpad-view%22%7D).", "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 2" }, + { + "view": "gitlens.views.scm.grouped", + "contents": "[Start Pro Trial](command:gitlens.plus.signUp?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nStart your free 7-day Pro trial to try Launchpad and other Pro features, or [sign in](command:gitlens.plus.login?%7B%22source%22%3A%22launchpad-view%22%7D).", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 2 && gitlens:views:scm:grouped:view == launchpad" + }, { "view": "gitlens.views.launchpad", "contents": "[Upgrade to Pro](command:gitlens.plus.upgrade?%7B%22source%22%3A%22launchpad-view%22%7D)", "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 4" }, + { + "view": "gitlens.views.scm.grouped", + "contents": "[Upgrade to Pro](command:gitlens.plus.upgrade?%7B%22source%22%3A%22launchpad-view%22%7D)", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 4 && gitlens:views:scm:grouped:view == launchpad" + }, { "view": "gitlens.views.launchpad", "contents": "Limited-time sale: Save 33% or more on your 1st seat of Pro.", "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 4 && (gitlens:promo == pro50 || !gitlens:promo)" }, + { + "view": "gitlens.views.scm.grouped", + "contents": "Limited-time sale: Save 33% or more on your 1st seat of Pro.", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 4 && (gitlens:promo == pro50 || !gitlens:promo) && gitlens:views:scm:grouped:view == launchpad" + }, { "view": "gitlens.views.launchpad", "contents": "Limited-time sale: Save up to 80% on GitLens Pro", "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 4 && gitlens:promo == devexdays" }, + { + "view": "gitlens.views.scm.grouped", + "contents": "Limited-time sale: Save up to 80% on GitLens Pro", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 4 && gitlens:promo == devexdays && gitlens:views:scm:grouped:view == launchpad" + }, { "view": "gitlens.views.launchpad", "contents": "Your Pro trial has ended. Please upgrade for full access to Launchpad and other Pro features.", "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 4" }, + { + "view": "gitlens.views.scm.grouped", + "contents": "Your Pro trial has ended. Please upgrade for full access to Launchpad and other Pro features.", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 4 && gitlens:views:scm:grouped:view == launchpad" + }, { "view": "gitlens.views.launchpad", "contents": "[Continue](command:gitlens.plus.reactivateProTrial?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nReactivate your Pro trial and experience Launchpad and all the new Pro features — free for another 7 days!", "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 5" }, + { + "view": "gitlens.views.scm.grouped", + "contents": "[Continue](command:gitlens.plus.reactivateProTrial?%7B%22source%22%3A%22launchpad-view%22%7D)\n\nReactivate your Pro trial and experience Launchpad and all the new Pro features — free for another 7 days!", + "when": "!gitlens:launchpad:connect && gitlens:plus:required && gitlens:plus:state == 5 && gitlens:views:scm:grouped:view == launchpad" + }, { "view": "gitlens.views.launchpad", "contents": "Pro feature — requires a paid plan for use on privately-hosted repos.", "when": "!gitlens:launchpad:connect" }, + { + "view": "gitlens.views.scm.grouped", + "contents": "Pro feature — requires a paid plan for use on privately-hosted repos.", + "when": "!gitlens:launchpad:connect && gitlens:views:scm:grouped:view == launchpad" + }, { "view": "gitlens.views.workspaces", "contents": "Workspaces ᴘʀᴇᴠɪᴇᴡ — group and manage multiple repositories together, accessible from anywhere, streamlining your workflow.\n\nCreate workspaces just for yourself or share (coming soon in GitLens) them with your team for faster onboarding and better collaboration." @@ -19263,8 +19462,9 @@ { "id": "gitlens.views.launchpad", "name": "Launchpad", + "when": "!(config.gitlens.views.scm.grouped.enabled && gitlens:views:scm:grouped:view == launchpad) && !gitlens:views:scm:grouped:refresh", "contextualTitle": "GitLens", - "icon": "$(rocket)", + "icon": "$(gitlens-launchpad-view)", "initialSize": 2, "visibility": "visible" }, @@ -19275,7 +19475,7 @@ "contextualTitle": "GitLens", "icon": "$(gitlens-cloud-patch)", "initialSize": 2, - "visibility": "visible" + "visibility": "collapsed" }, { "id": "gitlens.views.workspaces", @@ -19284,7 +19484,7 @@ "contextualTitle": "GitLens", "icon": "$(gitlens-workspaces-view)", "initialSize": 2, - "visibility": "visible" + "visibility": "collapsed" } ], "gitlensInspect": [ @@ -19446,7 +19646,7 @@ { "id": "gitlens.views.scm.grouped", "name": "GitLens", - "when": "!gitlens:disabled && config.gitlens.views.scm.grouped.enabled && (config.gitlens.views.scm.grouped.views.branches || config.gitlens.views.scm.grouped.views.commits || config.gitlens.views.scm.grouped.views.contributors || config.gitlens.views.scm.grouped.views.remotes || config.gitlens.views.scm.grouped.views.repositories || config.gitlens.views.scm.grouped.views.searchAndCompare || config.gitlens.views.scm.grouped.views.stashes || config.gitlens.views.scm.grouped.views.tags || config.gitlens.views.scm.grouped.views.worktrees) && !gitlens:views:scm:grouped:refresh", + "when": "!gitlens:disabled && config.gitlens.views.scm.grouped.enabled && (config.gitlens.views.scm.grouped.views.branches || config.gitlens.views.scm.grouped.views.commits || config.gitlens.views.scm.grouped.views.contributors || config.gitlens.views.scm.grouped.views.launchpad || config.gitlens.views.scm.grouped.views.remotes || config.gitlens.views.scm.grouped.views.repositories || config.gitlens.views.scm.grouped.views.searchAndCompare || config.gitlens.views.scm.grouped.views.stashes || config.gitlens.views.scm.grouped.views.tags || config.gitlens.views.scm.grouped.views.worktrees) && !gitlens:views:scm:grouped:refresh", "contextualTitle": "GitLens", "icon": "$(gitlens-gitlens)", "visibility": "visible" diff --git a/src/constants.views.ts b/src/constants.views.ts index 8de8cd0e14a92..0abe8f8c00916 100644 --- a/src/constants.views.ts +++ b/src/constants.views.ts @@ -26,6 +26,7 @@ export type GroupableTreeViewTypes = Extract< | 'branches' | 'commits' | 'contributors' + | 'launchpad' | 'remotes' | 'repositories' | 'searchAndCompare' diff --git a/src/views/launchpadView.ts b/src/views/launchpadView.ts index 8c3125bc03841..af01c967a5985 100644 --- a/src/views/launchpadView.ts +++ b/src/views/launchpadView.ts @@ -2,6 +2,7 @@ import type { ConfigurationChangeEvent, TreeViewVisibilityChangeEvent } from 'vs import { Disposable, ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, window } from 'vscode'; import type { OpenWalkthroughCommandArgs } from '../commands/walkthroughs'; import type { LaunchpadViewConfig, ViewFilesLayout } from '../config'; +import { proBadge } from '../constants'; import { Commands } from '../constants.commands'; import type { Container } from '../container'; import { AuthenticationRequiredError } from '../errors'; @@ -152,14 +153,17 @@ export class LaunchpadViewNode extends CacheableChildrenViewNode< } async getChildren(): Promise<(GroupingNode | LaunchpadItemNode)[]> { + this.view.description = this.view.grouped + ? `${this.view.name.toLocaleLowerCase()}\u00a0\u2022\u00a0 ${proBadge}` + : proBadge; + this.view.message = undefined; + if (this.children == null) { const access = await this.view.container.git.access(PlusFeatures.Launchpad); if (!access.allowed) return []; const children: (GroupingNode | LaunchpadItemNode)[] = []; - this.view.message = undefined; - const hasIntegrations = await this.view.container.launchpad.hasConnectedIntegration(); if (!hasIntegrations) { return []; @@ -220,8 +224,8 @@ export class LaunchpadView extends ViewBase<'launchpad', LaunchpadViewNode, Laun protected readonly configKey = 'launchpad'; private _disposable: Disposable | undefined; - constructor(container: Container) { - super(container, 'launchpad', 'Launchpad', 'launchpadView'); + constructor(container: Container, grouped?: boolean) { + super(container, 'launchpad', 'Launchpad', 'launchpadView', grouped); } override dispose() { @@ -229,6 +233,11 @@ export class LaunchpadView extends ViewBase<'launchpad', LaunchpadViewNode, Laun super.dispose(); } + override getViewDescription(count?: number): string { + const description = super.getViewDescription(count); + return description ? `${description} \u00a0\u2022\u00a0 ${proBadge}` : proBadge; + } + protected getRoot() { return new LaunchpadViewNode(this); } diff --git a/src/views/scmGroupedView.ts b/src/views/scmGroupedView.ts index df73e91037e75..a2830cd2e88d8 100644 --- a/src/views/scmGroupedView.ts +++ b/src/views/scmGroupedView.ts @@ -7,6 +7,7 @@ import { executeCommand, registerCommand } from '../system/vscode/command'; import { BranchesView } from './branchesView'; import { CommitsView } from './commitsView'; import { ContributorsView } from './contributorsView'; +import { LaunchpadView } from './launchpadView'; import { RemotesView } from './remotesView'; import { RepositoriesView } from './repositoriesView'; import { SearchAndCompareView } from './searchAndCompareView'; @@ -33,6 +34,7 @@ export class ScmGroupedView implements Disposable { registerCommand('gitlens.views.scm.grouped.branches', () => this.setView('branches', true)), registerCommand('gitlens.views.scm.grouped.commits', () => this.setView('commits', true)), registerCommand('gitlens.views.scm.grouped.contributors', () => this.setView('contributors', true)), + registerCommand('gitlens.views.scm.grouped.launchpad', () => this.setView('launchpad', true)), registerCommand('gitlens.views.scm.grouped.remotes', () => this.setView('remotes', true)), registerCommand('gitlens.views.scm.grouped.repositories', () => this.setView('repositories', true)), registerCommand('gitlens.views.scm.grouped.searchAndCompare', () => this.setView('searchAndCompare', true)), @@ -77,6 +79,8 @@ export class ScmGroupedView implements Disposable { return new CommitsView(this.container, true); case 'contributors': return new ContributorsView(this.container, true); + case 'launchpad': + return new LaunchpadView(this.container, true); case 'remotes': return new RemotesView(this.container, true); case 'repositories': diff --git a/src/views/views.ts b/src/views/views.ts index cc0267e622852..3b38da370275a 100644 --- a/src/views/views.ts +++ b/src/views/views.ts @@ -97,6 +97,7 @@ export class Views implements Disposable { this._branchesView?.dispose(); this._commitsView?.dispose(); this._contributorsView?.dispose(); + this._launchpadView?.dispose(); this._remotesView?.dispose(); this._repositoriesView?.dispose(); this._searchAndCompareView?.dispose(); @@ -151,6 +152,16 @@ export class Views implements Disposable { registerCommand('gitlens.views.scm.grouped.contributors.setAsDefault', () => this.setAsScmGroupedDefaultView('contributors'), ), + registerCommand('gitlens.views.launchpad.regroup', () => this.toggleScmViewGrouping('launchpad', true)), + registerCommand('gitlens.views.scm.grouped.launchpad.detach', () => + this.toggleScmViewGrouping('launchpad', false), + ), + registerCommand('gitlens.views.scm.grouped.launchpad.regroup', () => + this.toggleScmViewGrouping('launchpad', true), + ), + registerCommand('gitlens.views.scm.grouped.launchpad.setAsDefault', () => + this.setAsScmGroupedDefaultView('launchpad'), + ), registerCommand('gitlens.views.remotes.regroup', () => this.toggleScmViewGrouping('remotes', true)), registerCommand('gitlens.views.scm.grouped.remotes.detach', () => this.toggleScmViewGrouping('remotes', false), @@ -218,7 +229,6 @@ export class Views implements Disposable { return [ (this._draftsView = new DraftsView(this.container)), (this._fileHistoryView = new FileHistoryView(this.container)), - (this._launchpadView = new LaunchpadView(this.container)), (this._lineHistoryView = new LineHistoryView(this.container)), (this._pullRequestView = new PullRequestView(this.container)), (this._workspacesView = new WorkspacesView(this.container)), @@ -303,6 +313,13 @@ export class Views implements Disposable { this._contributorsView = undefined; } + if (!groupingEnabled || !this._scmGroupedViews.has('launchpad')) { + this._launchpadView ??= new LaunchpadView(this.container); + } else { + this._launchpadView?.dispose(); + this._launchpadView = undefined; + } + if (!groupingEnabled || !this._scmGroupedViews.has('remotes')) { this._remotesView ??= new RemotesView(this.container); } else { @@ -398,9 +415,9 @@ export class Views implements Disposable { return this._homeView; } - private _launchpadView!: LaunchpadView; + private _launchpadView!: LaunchpadView | undefined; get launchpad(): LaunchpadView { - return this._launchpadView; + return this._launchpadView ?? this._scmGroupedView.setView('launchpad'); } private _lineHistoryView!: LineHistoryView; @@ -595,8 +612,9 @@ const defaultScmGroupedViews: Record = Object.f tags: true, worktrees: true, contributors: true, - repositories: true, + repositories: false, searchAndCompare: true, + launchpad: false, }); function getScmGroupedViewsFromConfig() { @@ -622,5 +640,6 @@ async function updateScmGroupedViewsInConfig(groupedViews: Set diff --git a/src/webviews/apps/home/home.html b/src/webviews/apps/home/home.html index fb67e5dda8841..106a5ae2b626e 100644 --- a/src/webviews/apps/home/home.html +++ b/src/webviews/apps/home/home.html @@ -11,7 +11,7 @@ @font-face { font-family: 'glicons'; font-display: block; - src: url('#{root}/dist/glicons.woff2?526ab4b01522255557001d936894ca47') format('woff2'); + src: url('#{root}/dist/glicons.woff2?888557bf00e2cc234c92d4643f1f0051') format('woff2'); } diff --git a/src/webviews/apps/plus/graph/graph.html b/src/webviews/apps/plus/graph/graph.html index 0eb5bd552aff9..f66fe86c163e7 100644 --- a/src/webviews/apps/plus/graph/graph.html +++ b/src/webviews/apps/plus/graph/graph.html @@ -11,7 +11,7 @@ @font-face { font-family: 'glicons'; font-display: block; - src: url('#{root}/dist/glicons.woff2?526ab4b01522255557001d936894ca47') format('woff2'); + src: url('#{root}/dist/glicons.woff2?888557bf00e2cc234c92d4643f1f0051') format('woff2'); }