@@ -3,7 +3,8 @@ import { ThemeIcon } from 'vscode';
33import { GlyphChars , quickPickTitleMaxChars } from '../constants' ;
44import { Commands } from '../constants.commands' ;
55import { Container } from '../container' ;
6- import type { PlusFeatures } from '../features' ;
6+ import type { FeatureAccess , RepoFeatureAccess } from '../features' ;
7+ import { PlusFeatures } from '../features' ;
78import * as BranchActions from '../git/actions/branch' ;
89import * as CommitActions from '../git/actions/commit' ;
910import * as ContributorActions from '../git/actions/contributor' ;
@@ -43,6 +44,7 @@ import type { GitWorktree, WorktreeQuickPickItem } from '../git/models/worktree'
4344import { createWorktreeQuickPickItem , getWorktreesByBranch , sortWorktrees } from '../git/models/worktree' ;
4445import { remoteUrlRegex } from '../git/parsers/remoteParser' ;
4546import type { FocusCommandArgs } from '../plus/focus/focus' ;
47+ import { getApplicablePromo } from '../plus/gk/account/promos' ;
4648import { isSubscriptionPaidPlan , isSubscriptionPreviewTrialExpired } from '../plus/gk/account/subscription' ;
4749import {
4850 CommitApplyFileChangesCommandQuickPickItem ,
@@ -98,6 +100,7 @@ import {
98100 OpenRemoteResourceCommandQuickPickItem ,
99101} from '../quickpicks/remoteProviderPicker' ;
100102import { filterMap , filterMapAsync , intersection , isStringArray } from '../system/array' ;
103+ import { executeCommand } from '../system/command' ;
101104import { configuration } from '../system/configuration' ;
102105import { formatPath } from '../system/formatPath' ;
103106import { debounce } from '../system/function' ;
@@ -106,6 +109,7 @@ import { Logger } from '../system/logger';
106109import { getSettledValue } from '../system/promise' ;
107110import { pad , pluralize , truncate } from '../system/string' ;
108111import { openWorkspace } from '../system/utils' ;
112+ import { getIconPathUris } from '../system/vscode' ;
109113import type { ViewsWithRepositoryFolders } from '../views/viewBase' ;
110114import type {
111115 AsyncStepResultGenerator ,
@@ -136,6 +140,7 @@ import {
136140 ShowDetailsViewQuickInputButton ,
137141 ShowTagsToggleQuickInputButton ,
138142} from './quickCommand.buttons' ;
143+ import type { OpenWalkthroughCommandArgs } from './walkthroughs' ;
139144
140145export function appendReposToTitle <
141146 State extends { repo : Repository } | { repos : Repository [ ] } ,
@@ -2599,11 +2604,11 @@ function getShowRepositoryStatusStepItems<
25992604}
26002605
26012606export async function * ensureAccessStep <
2602- State extends PartialStepState & { repo : Repository } ,
2603- Context extends { repos : Repository [ ] ; title : string } ,
2604- > ( state : State , context : Context , feature : PlusFeatures ) : AsyncStepResultGenerator < void > {
2605- const access = await Container . instance . git . access ( feature , state . repo . path ) ;
2606- if ( access . allowed ) return undefined ;
2607+ State extends PartialStepState & { repo ? : Repository } ,
2608+ Context extends { title : string } ,
2609+ > ( state : State , context : Context , feature : PlusFeatures ) : AsyncStepResultGenerator < FeatureAccess | RepoFeatureAccess > {
2610+ const access = await Container . instance . git . access ( feature , state . repo ? .path ) ;
2611+ if ( access . allowed ) return access ;
26072612
26082613 const directives : DirectiveQuickPickItem [ ] = [ ] ;
26092614 let placeholder : string ;
@@ -2615,13 +2620,28 @@ export async function* ensureAccessStep<
26152620 ) ;
26162621 placeholder = 'You must verify your email before you can continue' ;
26172622 } else {
2618- if ( access . subscription . required == null ) return undefined ;
2623+ if ( access . subscription . required == null ) return access ;
2624+
2625+ let detail ;
2626+ const promo = getApplicablePromo ( access . subscription . current . state ) ;
2627+ if ( promo != null ) {
2628+ // NOTE: Don't add a default case, so that if we add a new promo the build will break without handling it
2629+ switch ( promo . key ) {
2630+ case 'pro50' :
2631+ detail = '$(star-full) Limited-Time Sale: Save 33% or more on your 1st seat of Pro' ;
2632+ break ;
2633+ case 'launchpad' :
2634+ case 'launchpad-extended' :
2635+ detail = `$(rocket) Launchpad Sale: Save 75% or more on GitLens Pro` ;
2636+ break ;
2637+ }
2638+ }
26192639
26202640 placeholder = 'Pro feature — requires a trial or paid plan for use on privately-hosted repos' ;
26212641 if ( isSubscriptionPaidPlan ( access . subscription . required ) && access . subscription . current . account != null ) {
26222642 placeholder = 'Pro feature — requires a paid plan for use on privately-hosted repos' ;
26232643 directives . push (
2624- createDirectiveQuickPickItem ( Directive . RequiresPaidSubscription , true ) ,
2644+ createDirectiveQuickPickItem ( Directive . RequiresPaidSubscription , true , { detail : detail } ) ,
26252645 createQuickPickSeparator ( ) ,
26262646 createDirectiveQuickPickItem ( Directive . Cancel ) ,
26272647 ) ;
@@ -2644,12 +2664,45 @@ export async function* ensureAccessStep<
26442664 }
26452665 }
26462666
2667+ switch ( feature ) {
2668+ case PlusFeatures . Focus :
2669+ directives . splice (
2670+ 0 ,
2671+ 0 ,
2672+ createDirectiveQuickPickItem ( Directive . Cancel , undefined , {
2673+ label : 'Launchpad prioritizes your pull requests to keep you focused and your team unblocked' ,
2674+ detail : 'Click to learn more about Launchpad' ,
2675+ iconPath : new ThemeIcon ( 'rocket' ) ,
2676+ onDidSelect : ( ) =>
2677+ void executeCommand < OpenWalkthroughCommandArgs > ( Commands . OpenWalkthrough , {
2678+ step : 'launchpad' ,
2679+ source : 'launchpad' ,
2680+ detail : 'info' ,
2681+ } ) ,
2682+ } ) ,
2683+ createQuickPickSeparator ( ) ,
2684+ ) ;
2685+ break ;
2686+ case PlusFeatures . Worktrees :
2687+ directives . splice (
2688+ 0 ,
2689+ 0 ,
2690+ createDirectiveQuickPickItem ( Directive . Noop , undefined , {
2691+ label : 'Worktrees minimize context switching by allowing simultaneous work on multiple branches' ,
2692+ iconPath : getIconPathUris ( Container . instance , 'icon-repo.svg' ) ,
2693+ } ) ,
2694+ ) ;
2695+ break ;
2696+ }
2697+
26472698 const step = createPickStep < DirectiveQuickPickItem > ( {
2648- title : appendReposToTitle ( context . title , state , context ) ,
2699+ title : context . title ,
26492700 placeholder : placeholder ,
26502701 items : directives ,
2702+ buttons : [ ] ,
2703+ isConfirmationStep : true ,
26512704 } ) ;
26522705
26532706 const selection : StepSelection < typeof step > = yield step ;
2654- return canPickStepContinue ( step , state , selection ) ? undefined : StepResultBreak ;
2707+ return canPickStepContinue ( step , state , selection ) ? access : StepResultBreak ;
26552708}
0 commit comments