diff --git a/CHANGELOG.md b/CHANGELOG.md index 80dfa71a5b9b3..13be4812ccad5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p - Removes the option to associate an issue from cards in the RECENT section of the _Home_ view ([#4333](https://github.com/gitkraken/vscode-gitlens/issues/4333)) - Combines the "Create Pull Request" and "Create with AI" buttons into a split button ([#4330](https://github.com/gitkraken/vscode-gitlens/issues/4330)) - On the _Home_ view in the active branch card replaces repository with a breadcrumb that has both the repository and current branch, where the repository is collapsible and is hidden by default ([#4332](https://github.com/gitkraken/vscode-gitlens/issues/4332)) +- Hides Walkthrough links and buttons in _Cursor_ because they are not applicable ([#3837](https://github.com/gitkraken/vscode-gitlens/issues/3837)) ### Fixed diff --git a/contributions.json b/contributions.json index 61395a432003a..5d14e99622875 100644 --- a/contributions.json +++ b/contributions.json @@ -1465,11 +1465,11 @@ }, "gitlens.getStarted": { "label": "Get Started", - "commandPalette": true, + "commandPalette": "gitlens:walkthroughSupported", "menus": { "extension/context": [ { - "when": "extension =~ /^eamodio.gitlens?$/ && extensionStatus == installed", + "when": "extension =~ /^eamodio.gitlens?$/ && extensionStatus == installed && gitlens:walkthroughSupported", "group": "9_gitlens", "order": 1 } @@ -7868,14 +7868,14 @@ "menus": { "view/item/context": [ { - "when": "viewItem == gitlens:views:drafts", + "when": "viewItem == gitlens:views:drafts && gitlens:walkthroughSupported", "group": "8_info", "order": 1 } ], "view/title": [ { - "when": "view == gitlens.views.drafts", + "when": "view == gitlens.views.drafts && gitlens:walkthroughSupported", "group": "8_info", "order": 1 } @@ -8847,21 +8847,21 @@ "menus": { "gitlens/views/grouped/launchpad": [ { - "when": "gitlens:views:scm:grouped:view == launchpad", + "when": "gitlens:views:scm:grouped:view == launchpad && gitlens:walkthroughSupported", "group": "2_gitlens_actions", "order": 1 } ], "view/item/context": [ { - "when": "viewItem == gitlens:views:launchpad", + "when": "viewItem == gitlens:views:launchpad && gitlens:walkthroughSupported", "group": "8_info", "order": 1 } ], "view/title": [ { - "when": "view == gitlens.views.launchpad", + "when": "view == gitlens.views.launchpad && gitlens:walkthroughSupported", "group": "8_info", "order": 1 } @@ -16781,7 +16781,12 @@ "order": 1, "welcomeContent": [ { - "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." + "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:walkthroughSupported" + }, + { + "contents": "Launchpad — organizes your pull requests into actionable groups to help you focus and keep your team unblocked.", + "when": "!gitlens:walkthroughSupported" }, { "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.", @@ -16888,7 +16893,11 @@ }, { "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:loading && gitlens:views:scm:grouped:view == launchpad" + "when": "!gitlens:views:scm:grouped:loading && gitlens:views:scm:grouped:view == launchpad && gitlens:walkthroughSupported" + }, + { + "contents": "Launchpad — organizes your pull requests into actionable groups to help you focus and keep your team unblocked.", + "when": "!gitlens:views:scm:grouped:loading && gitlens:views:scm:grouped:view == launchpad && !gitlens:walkthroughSupported" }, { "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.", diff --git a/package.json b/package.json index 3d4c1601f4ad6..6701197295aba 100644 --- a/package.json +++ b/package.json @@ -11033,6 +11033,10 @@ "command": "gitlens.fetchRepositories", "when": "gitlens:repos:withRemotes && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders" }, + { + "command": "gitlens.getStarted", + "when": "gitlens:walkthroughSupported" + }, { "command": "gitlens.ghpr.views.openOrCreateWorktree", "when": "false" @@ -14200,7 +14204,7 @@ "extension/context": [ { "command": "gitlens.getStarted", - "when": "extension =~ /^eamodio.gitlens?$/ && extensionStatus == installed", + "when": "extension =~ /^eamodio.gitlens?$/ && extensionStatus == installed && gitlens:walkthroughSupported", "group": "9_gitlens@1" }, { @@ -15512,7 +15516,7 @@ "gitlens/views/grouped/launchpad": [ { "command": "gitlens.views.launchpad.info", - "when": "gitlens:views:scm:grouped:view == launchpad", + "when": "gitlens:views:scm:grouped:view == launchpad && gitlens:walkthroughSupported", "group": "2_gitlens_actions@1" }, { @@ -18789,7 +18793,7 @@ }, { "command": "gitlens.views.drafts.info", - "when": "viewItem == gitlens:views:drafts", + "when": "viewItem == gitlens:views:drafts && gitlens:walkthroughSupported", "group": "8_info@1" }, { @@ -19004,7 +19008,7 @@ }, { "command": "gitlens.views.launchpad.info", - "when": "viewItem == gitlens:views:launchpad", + "when": "viewItem == gitlens:views:launchpad && gitlens:walkthroughSupported", "group": "8_info@1" }, { @@ -20874,7 +20878,7 @@ }, { "command": "gitlens.views.drafts.info", - "when": "view == gitlens.views.drafts", + "when": "view == gitlens.views.drafts && gitlens:walkthroughSupported", "group": "8_info@1" }, { @@ -21099,7 +21103,7 @@ }, { "command": "gitlens.views.launchpad.info", - "when": "view == gitlens.views.launchpad", + "when": "view == gitlens.views.launchpad && gitlens:walkthroughSupported", "group": "8_info@1" }, { @@ -23627,7 +23631,13 @@ }, { "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." + "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:walkthroughSupported" + }, + { + "view": "gitlens.views.launchpad", + "contents": "Launchpad — organizes your pull requests into actionable groups to help you focus and keep your team unblocked.", + "when": "!gitlens:walkthroughSupported" }, { "view": "gitlens.views.launchpad", @@ -23687,7 +23697,12 @@ { "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:loading && gitlens:views:scm:grouped:view == launchpad" + "when": "!gitlens:views:scm:grouped:loading && gitlens:views:scm:grouped:view == launchpad && gitlens:walkthroughSupported" + }, + { + "view": "gitlens.views.scm.grouped", + "contents": "Launchpad — organizes your pull requests into actionable groups to help you focus and keep your team unblocked.", + "when": "!gitlens:views:scm:grouped:loading && gitlens:views:scm:grouped:view == launchpad && !gitlens:walkthroughSupported" }, { "view": "gitlens.views.scm.grouped", diff --git a/src/commands/quickCommand.steps.ts b/src/commands/quickCommand.steps.ts index 4b2d215931326..a5cbcc9a8fe44 100644 --- a/src/commands/quickCommand.steps.ts +++ b/src/commands/quickCommand.steps.ts @@ -110,6 +110,7 @@ import { first, map } from '../system/iterable'; import { Logger } from '../system/logger'; import { getSettledValue } from '../system/promise'; import { pad, pluralize, truncate } from '../system/string'; +import { isWalkthroughSupported } from '../telemetry/walkthroughStateProvider'; import type { ViewsWithRepositoryFolders } from '../views/viewBase'; import type { AsyncStepResultGenerator, @@ -2795,21 +2796,23 @@ export async function* ensureAccessStep< switch (feature) { case 'launchpad': - directives.splice( - 0, - 0, - createDirectiveQuickPickItem(Directive.Cancel, undefined, { - label: 'Launchpad prioritizes your pull requests to keep you focused and your team unblocked', - detail: 'Click to learn more about Launchpad', - iconPath: new ThemeIcon('rocket'), - onDidSelect: () => - void executeCommand('gitlens.openWalkthrough', { - step: 'accelerate-pr-reviews', - source: { source: 'launchpad', detail: 'info' }, - }), - }), - createQuickPickSeparator(), - ); + if (isWalkthroughSupported()) { + directives.splice( + 0, + 0, + createDirectiveQuickPickItem(Directive.Cancel, undefined, { + label: 'Launchpad prioritizes your pull requests to keep you focused and your team unblocked', + detail: 'Click to learn more about Launchpad', + iconPath: new ThemeIcon('rocket'), + onDidSelect: () => + void executeCommand('gitlens.openWalkthrough', { + step: 'accelerate-pr-reviews', + source: { source: 'launchpad', detail: 'info' }, + }), + }), + createQuickPickSeparator(), + ); + } break; case 'startWork': directives.splice( diff --git a/src/constants.context.ts b/src/constants.context.ts index d495f55b62b15..89eebedf20e49 100644 --- a/src/constants.context.ts +++ b/src/constants.context.ts @@ -60,6 +60,7 @@ export type ContextKeys = { 'gitlens:views:scm:grouped:welcome': boolean; 'gitlens:vsls': boolean | 'host' | 'guest'; 'gitlens:window:annotated': AnnotationStatus; + 'gitlens:walkthroughSupported': boolean; } & Record<`gitlens:action:${string}`, number> & Record<`gitlens:feature:unsupported:${Features}`, boolean> & Record<`gitlens:key:${Keys}`, boolean> & diff --git a/src/container.ts b/src/container.ts index 7469d3546e791..9f41b6e4975e3 100644 --- a/src/container.ts +++ b/src/container.ts @@ -59,7 +59,7 @@ import { log } from './system/decorators/log'; import { Logger } from './system/logger'; import { TelemetryService } from './telemetry/telemetry'; import { UsageTracker } from './telemetry/usageTracker'; -import { WalkthroughStateProvider } from './telemetry/walkthroughStateProvider'; +import { isWalkthroughSupported, WalkthroughStateProvider } from './telemetry/walkthroughStateProvider'; import { GitTerminalLinkProvider } from './terminal/linkProvider'; import { GitDocumentTracker } from './trackers/documentTracker'; import { LineTracker } from './trackers/lineTracker'; @@ -205,7 +205,9 @@ export class Container { ); this._disposables.push((this._uri = new UriService(this))); this._disposables.push((this._subscription = new SubscriptionService(this, this._connection, previousVersion))); - this._disposables.push((this._walkthrough = new WalkthroughStateProvider(this))); + if (isWalkthroughSupported()) { + this._disposables.push((this._walkthrough = new WalkthroughStateProvider(this))); + } this._disposables.push((this._organizations = new OrganizationService(this, this._connection))); this._disposables.push((this._git = new GitProviderService(this))); @@ -713,8 +715,8 @@ export class Container { return this._usage; } - private readonly _walkthrough: WalkthroughStateProvider; - get walkthrough(): WalkthroughStateProvider { + private readonly _walkthrough: WalkthroughStateProvider | undefined; + get walkthrough(): WalkthroughStateProvider | undefined { return this._walkthrough; } diff --git a/src/plus/gk/subscriptionService.ts b/src/plus/gk/subscriptionService.ts index 4325fe6cd4fe8..124fbc4919e5e 100644 --- a/src/plus/gk/subscriptionService.ts +++ b/src/plus/gk/subscriptionService.ts @@ -62,6 +62,7 @@ import { flatten } from '../../system/object'; import { pauseOnCancelOrTimeout } from '../../system/promise'; import { pluralize } from '../../system/string'; import { createDisposable } from '../../system/unifiedDisposable'; +import { isWalkthroughSupported } from '../../telemetry/walkthroughStateProvider'; import { LoginUriPathPrefix } from './authenticationConnection'; import { authenticationProviderScopes } from './authenticationProvider'; import type { GKCheckInResponse } from './models/checkin'; @@ -482,13 +483,13 @@ export class SubscriptionService implements Disposable { void this.resendVerification(source); } } else if (isSubscriptionPaid(this._subscription)) { - const learn: MessageItem = { title: 'Learn More' }; + const learn: MessageItem | undefined = isWalkthroughSupported() ? { title: 'Learn More' } : undefined; const confirm: MessageItem = { title: 'Continue', isCloseAffordance: true }; const result = await window.showInformationMessage( `You are now on ${actual.name} and have full access to all GitLens Pro features.`, { modal: true }, confirm, - learn, + ...(learn ? [learn] : []), ); if (result === learn) { @@ -497,7 +498,7 @@ export class SubscriptionService implements Disposable { } else if (isSubscriptionTrial(this._subscription)) { const days = getSubscriptionTimeRemaining(this._subscription, 'days') ?? 0; - const learn: MessageItem = { title: 'Learn More' }; + const learn: MessageItem | undefined = isWalkthroughSupported() ? { title: 'Learn More' } : undefined; const confirm: MessageItem = { title: 'Continue', isCloseAffordance: true }; const result = await window.showInformationMessage( `Welcome to your ${effective.name} Trial.\n\nYou now have full access to all GitLens Pro features for ${ @@ -508,7 +509,7 @@ export class SubscriptionService implements Disposable { detail: 'Your trial also includes access to the GitKraken DevEx platform, unleashing powerful Git visualization & productivity capabilities everywhere you work: IDE, desktop, browser, and terminal.', }, confirm, - learn, + ...(learn ? [learn] : []), ); if (result === learn) { @@ -516,7 +517,9 @@ export class SubscriptionService implements Disposable { } } else { const upgrade: MessageItem = { title: 'Upgrade to Pro' }; - const learn: MessageItem = { title: 'Community vs. Pro' }; + const learn: MessageItem | undefined = isWalkthroughSupported() + ? { title: 'Community vs. Pro' } + : undefined; const confirm: MessageItem = { title: 'Continue', isCloseAffordance: true }; const result = await window.showInformationMessage( `You are now on ${actual.name}.`, @@ -525,7 +528,7 @@ export class SubscriptionService implements Disposable { detail: 'You only have access to Pro features on publicly-hosted repos. For full access to all Pro features, please upgrade to GitLens Pro.', }, upgrade, - learn, + ...(learn ? [learn] : []), confirm, ); diff --git a/src/plus/launchpad/launchpad.ts b/src/plus/launchpad/launchpad.ts index 68f956f6fbaa7..1c92ff43889fa 100644 --- a/src/plus/launchpad/launchpad.ts +++ b/src/plus/launchpad/launchpad.ts @@ -53,6 +53,7 @@ import { getScopedCounter } from '../../system/counter'; import { fromNow } from '../../system/date'; import { some } from '../../system/iterable'; import { interpolate, pluralize } from '../../system/string'; +import { isWalkthroughSupported } from '../../telemetry/walkthroughStateProvider'; import { ProviderBuildStatusState, ProviderPullRequestReviewState } from '../integrations/providers/models'; import type { LaunchpadCategorizedResult, LaunchpadItem } from './launchpadProvider'; import { @@ -1175,21 +1176,22 @@ export class LaunchpadCommand extends QuickCommand { context: Context, ): AsyncStepResultGenerator<{ connected: boolean | IntegrationIds; resume: () => void | undefined }> { const hasConnectedIntegration = some(context.connectedIntegrations.values(), c => c); - const confirmations: (QuickPickItemOfT | DirectiveQuickPickItem)[] = !hasConnectedIntegration - ? [ - createDirectiveQuickPickItem(Directive.Cancel, undefined, { - label: 'Launchpad prioritizes your pull requests to keep you focused and your team unblocked', - detail: 'Click to learn more about Launchpad', - iconPath: new ThemeIcon('rocket'), - onDidSelect: () => - void executeCommand('gitlens.openWalkthrough', { - step: 'accelerate-pr-reviews', - source: { source: 'launchpad', detail: 'info' }, - }), - }), - createQuickPickSeparator(), - ] - : []; + const confirmations: (QuickPickItemOfT | DirectiveQuickPickItem)[] = + !hasConnectedIntegration && isWalkthroughSupported() + ? [ + createDirectiveQuickPickItem(Directive.Cancel, undefined, { + label: 'Launchpad prioritizes your pull requests to keep you focused and your team unblocked', + detail: 'Click to learn more about Launchpad', + iconPath: new ThemeIcon('rocket'), + onDidSelect: () => + void executeCommand('gitlens.openWalkthrough', { + step: 'accelerate-pr-reviews', + source: { source: 'launchpad', detail: 'info' }, + }), + }), + createQuickPickSeparator(), + ] + : []; for (const integration of supportedLaunchpadIntegrations) { if (context.connectedIntegrations.get(integration)) { @@ -1249,7 +1251,7 @@ export class LaunchpadCommand extends QuickCommand { const step = this.createConfirmStep( `${this.title} \u00a0\u2022\u00a0 Connect an ${hasConnectedIntegration ? 'Additional ' : ''}Integration`, [ - ...(hasConnectedIntegration + ...(hasConnectedIntegration || !isWalkthroughSupported() ? [] : [ createDirectiveQuickPickItem(Directive.Cancel, undefined, { diff --git a/src/plus/launchpad/launchpadIndicator.ts b/src/plus/launchpad/launchpadIndicator.ts index d28ca0a4669ed..5ae9b8488470e 100644 --- a/src/plus/launchpad/launchpadIndicator.ts +++ b/src/plus/launchpad/launchpadIndicator.ts @@ -11,6 +11,7 @@ import { once } from '../../system/event'; import { groupByMap } from '../../system/iterable'; import { wait } from '../../system/promise'; import { pluralize } from '../../system/string'; +import { isWalkthroughSupported } from '../../telemetry/walkthroughStateProvider'; import type { ConnectionStateChangeEvent } from '../integrations/integrationService'; import type { LaunchpadCommandArgs } from './launchpad'; import type { LaunchpadItem, LaunchpadProvider, LaunchpadRefreshEvent } from './launchpadProvider'; @@ -252,12 +253,20 @@ export class LaunchpadIndicator implements Disposable { tooltip.isTrusted = true; tooltip.appendMarkdown(`GitLens Launchpad ${proBadge}\u00a0\u00a0\u00a0\u00a0—\u00a0\u00a0\u00a0\u00a0`); - tooltip.appendMarkdown(`[$(question)](command:gitlens.launchpad.indicator.action?%22info%22 "What is this?")`); + if (isWalkthroughSupported()) { + tooltip.appendMarkdown( + `[$(question)](command:gitlens.launchpad.indicator.action?%22info%22 "What is this?")`, + ); + } tooltip.appendMarkdown('\u00a0'); tooltip.appendMarkdown(`[$(gear)](command:workbench.action.openSettings?%22gitlens.launchpad%22 "Settings")`); tooltip.appendMarkdown('\u00a0\u00a0|\u00a0\u00a0'); tooltip.appendMarkdown(`[$(circle-slash) Hide](command:gitlens.launchpad.indicator.action?%22hide%22 "Hide")`); + const launchpadLink = isWalkthroughSupported() + ? '[Launchpad](command:gitlens.launchpad.indicator.action?%22info%22 "Learn about Launchpad")' + : 'Launchpad'; + if ( state === 'idle' || state === 'disconnected' || @@ -266,7 +275,7 @@ export class LaunchpadIndicator implements Disposable { ) { tooltip.appendMarkdown('\n\n---\n\n'); tooltip.appendMarkdown( - '[Launchpad](command:gitlens.launchpad.indicator.action?%22info%22 "Learn about Launchpad") organizes your pull requests into actionable groups to help you focus and keep your team unblocked.', + `${launchpadLink} organizes your pull requests into actionable groups to help you focus and keep your team unblocked.`, ); tooltip.appendMarkdown( "\n\nIt's always accessible using the `GitLens: Open Launchpad` command from the Command Palette.", diff --git a/src/system/-webview/cursor.ts b/src/system/-webview/cursor.ts new file mode 100644 index 0000000000000..65d413f030681 --- /dev/null +++ b/src/system/-webview/cursor.ts @@ -0,0 +1,9 @@ +import { env } from 'vscode'; + +/** + * Checks if the current IDE is Cursor + * @returns true if the current IDE is Cursor, false otherwise + */ +export function isCursor(): boolean { + return env.appName === 'Cursor'; +} diff --git a/src/telemetry/walkthroughStateProvider.ts b/src/telemetry/walkthroughStateProvider.ts index 487be3b5496ad..690d2960d8464 100644 --- a/src/telemetry/walkthroughStateProvider.ts +++ b/src/telemetry/walkthroughStateProvider.ts @@ -5,6 +5,7 @@ import type { TrackedUsageKeys } from '../constants.telemetry'; import type { Container } from '../container'; import type { SubscriptionChangeEvent } from '../plus/gk/subscriptionService'; import { setContext } from '../system/-webview/context'; +import { isCursor } from '../system/-webview/cursor'; import { wait } from '../system/promise'; import type { UsageChangeEvent } from './usageTracker'; @@ -161,6 +162,8 @@ export class WalkthroughStateProvider implements Disposable { private subscriptionState: SubscriptionState | undefined; constructor(private readonly container: Container) { + void setContext('gitlens:walkthroughSupported', true); + this.disposables.push( this._onDidChangeProgress, this.container.usage.onDidChange(this.onUsageChanged, this), @@ -319,3 +322,7 @@ export class WalkthroughStateProvider implements Disposable { return true; } } + +export function isWalkthroughSupported(): boolean { + return !isCursor(); +} diff --git a/src/uris/deepLinks/deepLinkService.ts b/src/uris/deepLinks/deepLinkService.ts index ba5ea3ea6cfae..73cba2186c62e 100644 --- a/src/uris/deepLinks/deepLinkService.ts +++ b/src/uris/deepLinks/deepLinkService.ts @@ -30,6 +30,7 @@ import { once } from '../../system/event'; import { Logger } from '../../system/logger'; import { maybeUri, normalizePath } from '../../system/path'; import { fromBase64 } from '../../system/string'; +import { isWalkthroughSupported } from '../../telemetry/walkthroughStateProvider'; import { showInspectView } from '../../webviews/commitDetails/actions'; import type { ShowWipArgs } from '../../webviews/commitDetails/protocol'; import type { ShowInCommitGraphCommandArgs } from '../../webviews/plus/graph/registration'; @@ -37,6 +38,7 @@ import type { DeepLink, DeepLinkProgress, DeepLinkRepoOpenType, DeepLinkServiceC import { AccountDeepLinkTypes, DeepLinkActionType, + DeepLinkCommandType, DeepLinkCommandTypeToCommand, DeepLinkServiceAction, DeepLinkServiceState, @@ -1510,6 +1512,12 @@ export class DeepLinkService implements Disposable { break; } + if (mainId === DeepLinkCommandType.Walkthrough && !isWalkthroughSupported()) { + action = DeepLinkServiceAction.DeepLinkErrored; + message = 'Invalid command type.'; + break; + } + const command = DeepLinkCommandTypeToCommand.get(mainId); if (command == null) { action = DeepLinkServiceAction.DeepLinkErrored; diff --git a/src/webviews/apps/home/components/feature-nav.ts b/src/webviews/apps/home/components/feature-nav.ts index ce1d2ceb208e0..29b8fa51642d3 100644 --- a/src/webviews/apps/home/components/feature-nav.ts +++ b/src/webviews/apps/home/components/feature-nav.ts @@ -196,21 +196,31 @@ export class GlFeatureNav extends GlElement { this.orgAllowsDrafts, () => html`