@@ -20,6 +20,7 @@ import type {
2020import { GlyphChars } from '../../../constants' ;
2121import { Commands } from '../../../constants.commands' ;
2222import type { StoredGraphFilters , StoredGraphRefType } from '../../../constants.storage' ;
23+ import { proPreviewLengthInDays , proTrialLengthInDays } from '../../../constants.subscription' ;
2324import type { GraphShownTelemetryContext , GraphTelemetryContext , TelemetryEvents } from '../../../constants.telemetry' ;
2425import type { Container } from '../../../container' ;
2526import { CancellationError } from '../../../errors' ;
@@ -97,6 +98,7 @@ import { getSearchQueryComparisonKey, parseSearchQuery } from '../../../git/sear
9798import { splitGitCommitMessage } from '../../../git/utils/commit-utils' ;
9899import { ReferencesQuickPickIncludes , showReferencePicker } from '../../../quickpicks/referencePicker' ;
99100import { showRepositoryPicker } from '../../../quickpicks/repositoryPicker' ;
101+ import { createFromDateDelta } from '../../../system/date' ;
100102import { gate } from '../../../system/decorators/gate' ;
101103import { debug , log } from '../../../system/decorators/log' ;
102104import type { Deferrable } from '../../../system/function' ;
@@ -136,6 +138,7 @@ import type {
136138 DidGetCountParams ,
137139 DidGetRowHoverParams ,
138140 DidSearchParams ,
141+ DidSetFeaturePreviewTrialParams ,
139142 DoubleClickedParams ,
140143 GetMissingAvatarsParams ,
141144 GetMissingRefsMetadataParams ,
@@ -206,6 +209,7 @@ import {
206209 DidChangeWorkingTreeNotification ,
207210 DidFetchNotification ,
208211 DidSearchNotification ,
212+ DidSetFeaturePreviewTrialNotification ,
209213 DoubleClickedCommandType ,
210214 EnsureRowRequest ,
211215 GetCountsRequest ,
@@ -294,6 +298,7 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
294298 [ DidChangeSubscriptionNotification , this . notifyDidChangeSubscription ] ,
295299 [ DidChangeWorkingTreeNotification , this . notifyDidChangeWorkingTree ] ,
296300 [ DidFetchNotification , this . notifyDidFetch ] ,
301+ [ DidSetFeaturePreviewTrialNotification , this . notifyDidSetFeaturePreviewTrial ] ,
297302 ] ) ;
298303 private _refsMetadata : Map < string , GraphRefMetadata | null > | null | undefined ;
299304 private _search : GitSearch | undefined ;
@@ -681,11 +686,58 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
681686 this . copyWorkingChangesToWorktree ,
682687 ) ,
683688 this . host . registerWebviewCommand ( 'gitlens.graph.generateCommitMessage' , this . generateCommitMessage ) ,
689+ this . host . registerWebviewCommand ( 'gitlens.graph.startFeaturePreviewTrial' , this . startFeaturePreviewTrial ) ,
684690 ) ;
685691
686692 return commands ;
687693 }
688694
695+ async startFeaturePreviewTrial ( ) {
696+ const timestamp = new Date ( ) ;
697+ const consumedDays : { startedOn : string ; expiresOn : string } [ ] = this . container . storage . get (
698+ `plus:featurePreviewTrial:graph:consumedDays` ,
699+ [ ] ,
700+ ) ;
701+
702+ // If it's still in the 24h trial, end here
703+ if ( consumedDays . length > 0 && new Date ( consumedDays [ consumedDays . length - 1 ] . expiresOn ) > timestamp ) {
704+ return ;
705+ }
706+
707+ if ( consumedDays . length >= proPreviewLengthInDays ) {
708+ void window . showInformationMessage (
709+ `You have already used your ${ proPreviewLengthInDays } days of previewing local Pro features.` ,
710+ ) ;
711+ return ;
712+ }
713+
714+ await this . container . storage . store ( `plus:featurePreviewTrial:graph:consumedDays` , [
715+ ...( consumedDays ?? [ ] ) ,
716+ {
717+ startedOn : timestamp . toISOString ( ) ,
718+ expiresOn : createFromDateDelta ( timestamp , { days : 1 } ) . toISOString ( ) ,
719+ } ,
720+ ] ) ;
721+
722+ if ( this . container . telemetry . enabled ) {
723+ this . container . telemetry . sendEvent (
724+ 'subscription/action' ,
725+ { action : `start-graph-preview-trial` } ,
726+ { source : 'graph' } ,
727+ ) ;
728+ }
729+
730+ void window . showInformationMessage (
731+ `You can now preview local Pro features for 1 day${
732+ consumedDays . length + 1 < proPreviewLengthInDays
733+ ? `, up to ${ proPreviewLengthInDays - ( consumedDays . length + 1 ) } more days`
734+ : ''
735+ } , or [start your free ${ proTrialLengthInDays } -day Pro trial](command:gitlens.plus.signUp "Start Pro Trial") for full access to Pro features.`,
736+ ) ;
737+
738+ void this . notifyDidSetFeaturePreviewTrial ( ) ;
739+ }
740+
689741 onWindowFocusChanged ( focused : boolean ) : void {
690742 this . isWindowFocused = focused ;
691743 }
@@ -1874,6 +1926,16 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
18741926 } ) ;
18751927 }
18761928
1929+ @debug ( )
1930+ private async notifyDidSetFeaturePreviewTrial ( ) {
1931+ if ( ! this . host . ready || ! this . host . visible ) {
1932+ this . host . addPendingIpcNotification ( DidSetFeaturePreviewTrialNotification , this . _ipcNotificationMap , this ) ;
1933+ return false ;
1934+ }
1935+
1936+ return this . host . notify ( DidSetFeaturePreviewTrialNotification , this . getStoredGraphPreviewTrial ( ) ) ;
1937+ }
1938+
18771939 @debug ( )
18781940 private async notifyDidChangeWorkingTree ( ) {
18791941 if ( ! this . host . ready || ! this . host . visible ) {
@@ -2516,6 +2578,8 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
25162578
25172579 const defaultSearchMode = this . container . storage . get ( 'graph:searchMode' ) ?? 'normal' ;
25182580
2581+ const graphPreviewTrial = this . getStoredGraphPreviewTrial ( ) ;
2582+
25192583 return {
25202584 ...this . host . baseWebviewState ,
25212585 windowFocused : this . isWindowFocused ,
@@ -2563,6 +2627,7 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
25632627 nonce : this . host . cspNonce ,
25642628 workingTreeStats : getSettledValue ( workingStatsResult ) ?? { added : 0 , deleted : 0 , modified : 0 } ,
25652629 defaultSearchMode : defaultSearchMode ,
2630+ graphPreviewTrial : graphPreviewTrial ,
25662631 } ;
25672632 }
25682633
@@ -2837,6 +2902,18 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
28372902 return refs ;
28382903 }
28392904
2905+ private getStoredGraphPreviewTrial ( ) : DidSetFeaturePreviewTrialParams {
2906+ const storedValue = this . container . storage . get ( `plus:featurePreviewTrial:graph:consumedDays` , [ ] ) ;
2907+ return {
2908+ feature : 'graph' ,
2909+ consumedDays : storedValue ,
2910+ isActive :
2911+ storedValue . length > 0 &&
2912+ storedValue . length <= proPreviewLengthInDays &&
2913+ new Date ( storedValue [ storedValue . length - 1 ] . expiresOn ) > new Date ( ) ,
2914+ } ;
2915+ }
2916+
28402917 private updateIncludeOnlyRefs (
28412918 repoPath : string | undefined ,
28422919 { branchesVisibility, refs } : UpdateIncludedRefsParams ,
0 commit comments