Skip to content

Commit ab6374f

Browse files
committed
Adds subscription state to completion
1 parent d599d41 commit ab6374f

File tree

2 files changed

+90
-31
lines changed

2 files changed

+90
-31
lines changed

src/container.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@ export class Container {
179179
(this._storage = storage),
180180
(this._telemetry = new TelemetryService(this)),
181181
(this._usage = new UsageTracker(this, storage)),
182-
(this._walkthrough = new WalkthroughStateProvider(this)),
183182
configuration.onDidChangeAny(this.onAnyConfigurationChanged, this),
184183
];
185184

@@ -190,6 +189,7 @@ export class Container {
190189
);
191190
this._disposables.push((this._uri = new UriService(this)));
192191
this._disposables.push((this._subscription = new SubscriptionService(this, this._connection, previousVersion)));
192+
this._disposables.push((this._walkthrough = new WalkthroughStateProvider(this)));
193193
this._disposables.push((this._organizations = new OrganizationService(this, this._connection)));
194194

195195
this._disposables.push((this._git = new GitProviderService(this)));

src/telemetry/walkthroughStateProvider.ts

Lines changed: 89 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import type { Event } from 'vscode';
22
import { Disposable, EventEmitter } from 'vscode';
33
import { Commands } from '../constants.commands';
4+
import { SubscriptionState } from '../constants.subscription';
45
import type { TrackedUsageKeys } from '../constants.telemetry';
56
import type { Container } from '../container';
7+
import type { SubscriptionChangeEvent } from '../plus/gk/account/subscriptionService';
68
import { wait } from '../system/promise';
79
import { setContext } from '../system/vscode/context';
810
import type { UsageChangeEvent } from './usageTracker';
@@ -15,7 +17,23 @@ export enum WalkthroughContextKeys {
1517
Integrations = 'integrations',
1618
}
1719

18-
type WalkthroughUsage = { states: TrackedUsageKeys[]; usage: TrackedUsageKeys[] };
20+
type WalkthroughUsage = {
21+
subscriptionStates?: SubscriptionState[] | Readonly<SubscriptionState[]>;
22+
subscriptionCommands?: TrackedUsageKeys[] | Readonly<TrackedUsageKeys[]>;
23+
usage: TrackedUsageKeys[];
24+
};
25+
26+
const triedProStates: Readonly<SubscriptionState[]> = [
27+
SubscriptionState.ProTrial,
28+
SubscriptionState.ProTrialExpired,
29+
SubscriptionState.ProTrialReactivationEligible,
30+
SubscriptionState.Paid,
31+
];
32+
33+
const tryProCommands: Readonly<TrackedUsageKeys[]> = [
34+
`command:${Commands.PlusStartPreviewTrial}:executed`,
35+
`command:${Commands.PlusReactivateProTrial}:executed`,
36+
];
1937

2038
const walkthroughRequiredMapping: Readonly<Map<WalkthroughContextKeys, WalkthroughUsage>> = new Map<
2139
WalkthroughContextKeys,
@@ -24,22 +42,16 @@ const walkthroughRequiredMapping: Readonly<Map<WalkthroughContextKeys, Walkthrou
2442
[
2543
WalkthroughContextKeys.GettingStarted,
2644
{
27-
states: [
28-
`command:${Commands.PlusStartPreviewTrial}:executed`,
29-
`command:${Commands.PlusReactivateProTrial}:executed`,
30-
`command:${Commands.OpenWalkthrough}:executed`,
31-
`command:${Commands.GetStarted}:executed`,
32-
],
45+
subscriptionStates: triedProStates,
46+
subscriptionCommands: tryProCommands,
3347
usage: [],
3448
},
3549
],
3650
[
3751
WalkthroughContextKeys.VisualizeCodeHistory,
3852
{
39-
states: [
40-
`command:${Commands.PlusStartPreviewTrial}:executed`,
41-
`command:${Commands.PlusReactivateProTrial}:executed`,
42-
],
53+
subscriptionStates: triedProStates,
54+
subscriptionCommands: tryProCommands,
4355
usage: [
4456
'graphDetailsView:shown',
4557
'graphView:shown',
@@ -56,10 +68,8 @@ const walkthroughRequiredMapping: Readonly<Map<WalkthroughContextKeys, Walkthrou
5668
[
5769
WalkthroughContextKeys.PrReviews,
5870
{
59-
states: [
60-
`command:${Commands.PlusStartPreviewTrial}:executed`,
61-
`command:${Commands.PlusReactivateProTrial}:executed`,
62-
],
71+
subscriptionStates: triedProStates,
72+
subscriptionCommands: tryProCommands,
6373
usage: [
6474
'launchpadView:shown',
6575
'worktreesView:shown',
@@ -75,17 +85,14 @@ const walkthroughRequiredMapping: Readonly<Map<WalkthroughContextKeys, Walkthrou
7585
[
7686
WalkthroughContextKeys.StreamlineCollaboration,
7787
{
78-
states: [
79-
`command:${Commands.PlusStartPreviewTrial}:executed`,
80-
`command:${Commands.PlusReactivateProTrial}:executed`,
81-
],
88+
subscriptionStates: triedProStates,
89+
subscriptionCommands: tryProCommands,
8290
usage: [`command:${Commands.CreateCloudPatch}:executed`, `command:${Commands.CreatePatch}:executed`],
8391
},
8492
],
8593
[
8694
WalkthroughContextKeys.Integrations,
8795
{
88-
states: [],
8996
usage: [
9097
`command:${Commands.PlusConnectCloudIntegrations}:executed`,
9198
`command:${Commands.PlusManageCloudIntegrations}:executed`,
@@ -95,23 +102,28 @@ const walkthroughRequiredMapping: Readonly<Map<WalkthroughContextKeys, Walkthrou
95102
]);
96103

97104
export class WalkthroughStateProvider implements Disposable {
105+
readonly walkthroughSize = walkthroughRequiredMapping.size;
98106
protected disposables: Disposable[] = [];
99107
private readonly completed = new Set<WalkthroughContextKeys>();
100-
readonly walkthroughSize: number;
108+
private subscriptionState: SubscriptionState | undefined;
101109

102110
private readonly _onProgressChanged = new EventEmitter<void>();
103111
get onProgressChanged(): Event<void> {
104112
return this._onProgressChanged.event;
105113
}
106114

107115
constructor(private readonly container: Container) {
108-
this.disposables.push(this.container.usage.onDidChange(this.onUsageChanged, this));
109-
this.walkthroughSize = walkthroughRequiredMapping.size;
116+
this.disposables.push(
117+
this.container.usage.onDidChange(this.onUsageChanged, this),
118+
this.container.subscription.onDidChange(this.onSubscriptionChanged, this),
119+
);
110120

111-
this.initializeState();
121+
void this.initializeState();
112122
}
113123

114-
private initializeState() {
124+
private async initializeState() {
125+
this.subscriptionState = (await this.container.subscription.getSubscription(true)).state;
126+
115127
for (const key of walkthroughRequiredMapping.keys()) {
116128
if (this.validateStep(key)) {
117129
void this.completeStep(key);
@@ -147,6 +159,29 @@ export class WalkthroughStateProvider implements Disposable {
147159
}
148160
}
149161

162+
private onSubscriptionChanged(e: SubscriptionChangeEvent) {
163+
this.subscriptionState = e.current.state;
164+
const stepsToValidate = this.getStepsFromSubscriptionState(e.current.state);
165+
let shouldFire = false;
166+
for (const step of stepsToValidate) {
167+
// no need to check if the step is already completed
168+
if (this.completed.has(step)) {
169+
continue;
170+
}
171+
172+
if (this.validateStep(step)) {
173+
void this.completeStep(step);
174+
this.container.telemetry.sendEvent('walkthrough/completion', {
175+
'context.key': step,
176+
});
177+
shouldFire = true;
178+
}
179+
}
180+
if (shouldFire) {
181+
this._onProgressChanged.fire(undefined);
182+
}
183+
}
184+
150185
private _isInitialized: boolean = false;
151186
private _initPromise: Promise<void> | undefined;
152187
/**
@@ -191,8 +226,19 @@ export class WalkthroughStateProvider implements Disposable {
191226

192227
private getStepsFromUsage(usageKey: TrackedUsageKeys): WalkthroughContextKeys[] {
193228
const keys: WalkthroughContextKeys[] = [];
194-
for (const [key, { states, usage: events }] of walkthroughRequiredMapping) {
195-
if (states.includes(usageKey) || events.includes(usageKey)) {
229+
for (const [key, { subscriptionCommands, usage }] of walkthroughRequiredMapping) {
230+
if (subscriptionCommands?.includes(usageKey) || usage.includes(usageKey)) {
231+
keys.push(key);
232+
}
233+
}
234+
235+
return keys;
236+
}
237+
238+
private getStepsFromSubscriptionState(_state: SubscriptionState): WalkthroughContextKeys[] {
239+
const keys: WalkthroughContextKeys[] = [];
240+
for (const [key, { subscriptionStates }] of walkthroughRequiredMapping) {
241+
if (subscriptionStates != null) {
196242
keys.push(key);
197243
}
198244
}
@@ -201,11 +247,24 @@ export class WalkthroughStateProvider implements Disposable {
201247
}
202248

203249
private validateStep(key: WalkthroughContextKeys): boolean {
204-
const { states, usage: events } = walkthroughRequiredMapping.get(key)!;
205-
if (states.length && !states.some(state => this.container.usage.isUsed(state))) {
250+
const { subscriptionStates, subscriptionCommands, usage } = walkthroughRequiredMapping.get(key)!;
251+
252+
let subscriptionState: boolean | undefined;
253+
if (subscriptionStates != null && subscriptionStates.length > 0) {
254+
subscriptionState = this.subscriptionState != null && subscriptionStates.includes(this.subscriptionState);
255+
}
256+
let subscriptionCommandState: boolean | undefined;
257+
if (subscriptionCommands != null && subscriptionCommands.length > 0) {
258+
subscriptionCommandState = subscriptionCommands.some(event => this.container.usage.isUsed(event));
259+
}
260+
if (
261+
(subscriptionState === undefined && subscriptionCommandState === false) ||
262+
(subscriptionState === false && subscriptionCommandState !== true)
263+
) {
206264
return false;
207265
}
208-
if (events.length && !events.some(event => this.container.usage.isUsed(event))) {
266+
267+
if (usage.length > 0 && !usage.some(event => this.container.usage.isUsed(event))) {
209268
return false;
210269
}
211270
return true;

0 commit comments

Comments
 (0)