From ffb876aa7c032b0ace173b533111b1e94ff6151f Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Wed, 2 Mar 2022 21:27:09 -0500 Subject: [PATCH] Reframes premium to GitLens+ Trying to improve clarity that there are only a small subset of features that require an account --- package.json | 78 +++++++++++----------- src/commands/git/worktree.ts | 4 +- src/commands/quickCommand.steps.ts | 8 +-- src/config.ts | 2 +- src/constants.ts | 30 ++++----- src/env/node/git/localGitProvider.ts | 8 +-- src/features.ts | 2 +- src/git/gitProvider.ts | 4 +- src/git/gitProviderService.ts | 10 +-- src/git/models/repository.ts | 4 +- src/premium/github/githubGitProvider.ts | 8 +-- src/premium/subscription/authenticationProvider.ts | 8 +-- src/premium/subscription/subscriptionService.ts | 71 ++++++++++---------- src/premium/subscription/utils.ts | 8 +-- src/premium/webviews/timeline/timelineWebview.ts | 8 +-- .../webviews/timeline/timelineWebviewView.ts | 8 +-- src/quickpicks/items/directive.ts | 10 +-- src/storage.ts | 3 +- src/subscription.ts | 10 +-- src/views/nodes/worktreesNode.ts | 8 +-- src/views/worktreesView.ts | 10 +-- src/webviews/apps/home/partials/links.html | 2 +- .../home/partials/state.free-preview-expired.html | 51 ++++---------- .../apps/home/partials/state.free-preview.html | 21 +++--- src/webviews/apps/home/partials/state.free.html | 20 +++--- src/webviews/apps/home/partials/state.paid.html | 10 +-- .../home/partials/state.plus-trial-expired.html | 12 ++-- .../apps/home/partials/state.plus-trial.html | 46 +++---------- .../apps/home/partials/state.verify-email.html | 2 +- .../partials/state.free-preview-expired.html | 12 ++-- .../apps/premium/timeline/partials/state.free.html | 8 +-- src/webviews/apps/welcome/welcome.html | 2 +- src/webviews/home/homeWebviewView.ts | 4 +- walkthroughs/getting-started/12-plus.md | 13 ++++ .../getting-started/12-premium-features.md | 7 -- walkthroughs/plus/1-intro.md | 27 ++++---- walkthroughs/plus/4-coming-soon.md | 4 +- 37 files changed, 247 insertions(+), 296 deletions(-) create mode 100644 walkthroughs/getting-started/12-plus.md delete mode 100644 walkthroughs/getting-started/12-premium-features.md diff --git a/package.json b/package.json index c4ac118..d156295 100644 --- a/package.json +++ b/package.json @@ -3264,7 +3264,7 @@ "gitlens.plusFeatures.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to enable premium features", + "markdownDescription": "Specifies whether to enable GitLens+ features", "scope": "window", "order": 60 }, @@ -3615,48 +3615,48 @@ "commands": [ { "command": "gitlens.plus.learn", - "title": "Learn about Premium Features", - "category": "GitLens" + "title": "Learn about GitLens+ Features", + "category": "GitLens+" }, { "command": "gitlens.plus.loginOrSignUp", - "title": "Sign In (for premium features)...", - "category": "GitLens Premium" + "title": "Sign In to GitLens+...", + "category": "GitLens+" }, { "command": "gitlens.plus.logout", - "title": "Disconnect Account", - "category": "GitLens Premium" + "title": "Disconnect from GitLens+", + "category": "GitLens+" }, { "command": "gitlens.plus.startPreviewTrial", - "title": "Try Premium Features Now", - "category": "GitLens Premium" + "title": "Try GitLens+ Features Now", + "category": "GitLens+" }, { "command": "gitlens.plus.manage", - "title": "Manage Your Account...", - "category": "GitLens Premium" + "title": "Manage Your GitLens+ Account...", + "category": "GitLens+" }, { "command": "gitlens.plus.purchase", - "title": "Upgrade Your Account...", - "category": "GitLens Premium" + "title": "Upgrade Your GitLens+ Account...", + "category": "GitLens+" }, { "command": "gitlens.plus.hide", - "title": "Hide Premium Features...", - "category": "GitLens Premium" + "title": "Hide GitLens+ Features...", + "category": "GitLens+" }, { "command": "gitlens.plus.restore", - "title": "Restore Premium Features...", - "category": "GitLens Premium" + "title": "Restore GitLens+ Features...", + "category": "GitLens+" }, { "command": "gitlens.plus.reset", "title": "Reset...", - "category": "GitLens Premium" + "category": "GitLens+" }, { "command": "gitlens.getStarted", @@ -5959,19 +5959,19 @@ "commandPalette": [ { "command": "gitlens.plus.loginOrSignUp", - "when": "!gitlens:premium" + "when": "!gitlens:plus" }, { "command": "gitlens.plus.logout", - "when": "gitlens:premium" + "when": "gitlens:plus" }, { "command": "gitlens.plus.startPreviewTrial", - "when": "!gitlens:premium" + "when": "!gitlens:plus" }, { "command": "gitlens.plus.manage", - "when": "gitlens:premium" + "when": "gitlens:plus" }, { "command": "gitlens.plus.hide", @@ -10679,12 +10679,12 @@ }, { "view": "gitlens.views.worktrees", - "contents": "Try worktrees now, without an account, for 3 days on public and private repos, or [sign in](command:gitlens.plus.loginOrSignUp \"Sign in now\") for unlimited use on public repos.\n\n[Try worktrees now](command:gitlens.plus.startPreviewTrial)", + "contents": "Try worktrees now, without an account, for 3 days on public and private repos, or [sign in](command:gitlens.plus.loginOrSignUp \"Sign in to GitLens+\") for use on public repos.\n\n[Try worktrees now](command:gitlens.plus.startPreviewTrial)", "when": "gitlens:plus:state == 0" }, { "view": "gitlens.views.worktrees", - "contents": "Sign in to use worktrees and other premium features on public repos and get a free 7-day trial for both public and private repos.\n\n[Sign in](command:gitlens.plus.loginOrSignUp)", + "contents": "Sign in to use worktrees and other GitLens+ features on public repos and get a free 7-day trial for both public and private repos.\n\n[Sign in to GitLens+](command:gitlens.plus.loginOrSignUp)", "when": "gitlens:plus:state == 2" }, { @@ -10694,7 +10694,7 @@ }, { "view": "gitlens.views.worktrees", - "contents": "✨ Worktrees are a [premium feature](command:gitlens.plus.learn) which can be used on public repos with a [free account](command:gitlens.plus.loginOrSignUp) and private repos with a [paid account](command:gitlens.plus.purchase).\n\n🛈 Non-premium features can always be used on any repo.", + "contents": "✨ Worktrees are a [GitLens+ feature](command:gitlens.plus.learn) which can be used on public repos with a [free account](command:gitlens.plus.loginOrSignUp) and private repos with a [paid account](command:gitlens.plus.purchase).\n\n🛈 All other GitLens features can always be used on any repo.", "when": "gitlens:plus:state > -1" } ], @@ -10907,24 +10907,24 @@ } }, { - "id": "gitlens.welcome.premium", - "title": "✨ Premium features", - "description": "New premium features like Visual File History and Worktrees are now available in GitLens.\n\n[Learn about Premium Features](command:gitlens.plus.learn?false \"Opens the GitLens Premium Features walkthrough\")", + "id": "gitlens.welcome.plus", + "title": "Introducing GitLens+", + "description": "Check out the all-new, completely optional, GitLens+ features.\n\n[Learn about GitLens+ features](command:gitlens.plus.learn?false \"Open the GitLens+ features walkthrough\")", "media": { - "markdown": "walkthroughs/getting-started/12-premium-features.md" + "markdown": "walkthroughs/getting-started/12-plus.md" } } ] }, { "id": "gitlens.plus", - "title": "GitLens Premium Features", + "title": "Introducing GitLens+", "description": "Get even more out of GitLens in VS Code!", "steps": [ { "id": "gitlens.plus.intro.tryNow", - "title": "Introducing premium features", - "description": "Try premium features now, without an account, for 3 days.\n\n[Try premium features now](command:gitlens.plus.startPreviewTrial)", + "title": "Introducing GitLens+", + "description": "Try GitLens+ features now, without an account, for 3 days.\n\n[Try GitLens+ features now](command:gitlens.plus.startPreviewTrial)", "media": { "markdown": "walkthroughs/plus/1-intro.md" }, @@ -10932,8 +10932,8 @@ }, { "id": "gitlens.plus.intro.signIn", - "title": "Introducing premium features", - "description": "Sign in for an additional 7 day trial of premium features.\n\n[Sign in](command:gitlens.plus.loginOrSignUp)", + "title": "Introducing GitLens+", + "description": "Sign in for use on public repos and get an additional 7 day trial for private repos.\n\n[Sign in to GitLens+](command:gitlens.plus.loginOrSignUp)", "media": { "markdown": "walkthroughs/plus/1-intro.md" }, @@ -10941,7 +10941,7 @@ }, { "id": "gitlens.plus.intro", - "title": "Introducing premium features", + "title": "Introducing GitLens+", "media": { "markdown": "walkthroughs/plus/1-intro.md" }, @@ -10973,8 +10973,8 @@ }, { "id": "gitlens.plus.tryNow", - "title": "Try premium features now", - "description": "Try premium features now, without an account, for 3 days.\n\n[Try premium features now](command:gitlens.plus.startPreviewTrial)", + "title": "Try GitLens+ now", + "description": "Try GitLens+ features now, without an account, for 3 days.\n\n[Try GitLens+ features now](command:gitlens.plus.startPreviewTrial)", "media": { "markdown": "walkthroughs/plus/5-try-now.md" }, @@ -10982,8 +10982,8 @@ }, { "id": "gitlens.plus.signIn", - "title": "Extend your premium features trial", - "description": "Sign in for an additional 7 day trial of premium features.\n\n[Sign in](command:gitlens.plus.loginOrSignUp)", + "title": "Get access to GitLens+ features on public repos", + "description": "Sign in for use on public repos and get an additional 7 day trial for private repos.\n\n[Sign in to GitLens+](command:gitlens.plus.loginOrSignUp)", "media": { "markdown": "walkthroughs/plus/5-try-now.md" }, diff --git a/src/commands/git/worktree.ts b/src/commands/git/worktree.ts index c5c3459..7c2af06 100644 --- a/src/commands/git/worktree.ts +++ b/src/commands/git/worktree.ts @@ -1,7 +1,7 @@ import { MessageItem, QuickInputButtons, Uri, window } from 'vscode'; import { configuration } from '../../configuration'; import { Container } from '../../container'; -import { PremiumFeatures } from '../../features'; +import { PlusFeatures } from '../../features'; import { WorktreeCreateError, WorktreeCreateErrorReason, @@ -200,7 +200,7 @@ export class WorktreeGitCommand extends QuickCommand { } } - const result = yield* ensureAccessStep(state as any, context, PremiumFeatures.Worktrees); + const result = yield* ensureAccessStep(state as any, context, PlusFeatures.Worktrees); if (result === StepResult.Break) break; context.title = getTitle(state.subcommand === 'delete' ? 'Worktrees' : this.title, state.subcommand); diff --git a/src/commands/quickCommand.steps.ts b/src/commands/quickCommand.steps.ts index 6b749bb..656fa5c 100644 --- a/src/commands/quickCommand.steps.ts +++ b/src/commands/quickCommand.steps.ts @@ -2,7 +2,7 @@ import { QuickInputButton, QuickPick } from 'vscode'; import { BranchSorting, configuration, TagSorting } from '../configuration'; import { Commands, GlyphChars, quickPickTitleMaxChars } from '../constants'; import { Container } from '../container'; -import type { PremiumFeatures } from '../features'; +import type { PlusFeatures } from '../features'; import type { PagedResult } from '../git/gitProvider'; import { BranchSortOptions, @@ -2233,7 +2233,7 @@ function getShowRepositoryStatusStepItems< export async function* ensureAccessStep< State extends PartialStepState & { repo: Repository }, Context extends { repos: Repository[]; title: string }, ->(state: State, context: Context, feature: PremiumFeatures): AsyncStepResultGenerator { +>(state: State, context: Context, feature: PlusFeatures): AsyncStepResultGenerator { const access = await Container.instance.git.access(feature, state.repo.path); if (access.allowed) return undefined; @@ -2247,7 +2247,7 @@ export async function* ensureAccessStep< if (isSubscriptionPaidPlan(access.subscription.required) && access.subscription.current.account != null) { directives.push(DirectiveQuickPickItem.create(Directive.RequiresPaidSubscription, true)); - placeholder = 'Premium features require an upgraded account'; + placeholder = 'GitLens+ features require an upgraded account'; } else { if ( access.subscription.current.account == null && @@ -2260,7 +2260,7 @@ export async function* ensureAccessStep< } else { directives.push(DirectiveQuickPickItem.create(Directive.RequiresFreeSubscription)); } - placeholder = 'Premium features require an account'; + placeholder = 'GitLens+ features require a free account'; } } diff --git a/src/config.ts b/src/config.ts index 8aec948..e58b539 100644 --- a/src/config.ts +++ b/src/config.ts @@ -113,7 +113,7 @@ export interface Config { [key: string]: any; } > | null; - premiumFeatures: { + plusFeatures: { enabled: boolean; }; remotes: RemotesConfig[] | null; diff --git a/src/constants.ts b/src/constants.ts index ac49a9c..7bdd365 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -137,17 +137,17 @@ export const enum Commands { GitCommandsSwitch = 'gitlens.gitCommands.switch', GitCommandsTag = 'gitlens.gitCommands.tag', GitCommandsWorktree = 'gitlens.gitCommands.worktree', - PremiumHide = 'gitlens.plus.hide', - PremiumLearn = 'gitlens.plus.learn', - PremiumLoginOrSignUp = 'gitlens.plus.loginOrSignUp', - PremiumLogout = 'gitlens.plus.logout', - PremiumManage = 'gitlens.plus.manage', - PremiumPurchase = 'gitlens.plus.purchase', - PremiumResendVerification = 'gitlens.plus.resendVerification', - PremiumRestore = 'gitlens.plus.restore', - PremiumShowPlans = 'gitlens.plus.showPlans', - PremiumStartPreviewTrial = 'gitlens.plus.startPreviewTrial', - PremiumValidate = 'gitlens.plus.validate', + PlusHide = 'gitlens.plus.hide', + PlusLearn = 'gitlens.plus.learn', + PlusLoginOrSignUp = 'gitlens.plus.loginOrSignUp', + PlusLogout = 'gitlens.plus.logout', + PlusManage = 'gitlens.plus.manage', + PlusPurchase = 'gitlens.plus.purchase', + PlusResendVerification = 'gitlens.plus.resendVerification', + PlusRestore = 'gitlens.plus.restore', + PlusShowPlans = 'gitlens.plus.showPlans', + PlusStartPreviewTrial = 'gitlens.plus.startPreviewTrial', + PlusValidate = 'gitlens.plus.validate', QuickOpenFileHistory = 'gitlens.quickOpenFileHistory', RefreshHover = 'gitlens.refreshHover', ResetAvatarCache = 'gitlens.resetAvatarCache', @@ -257,10 +257,10 @@ export const enum ContextKeys { ViewsSearchAndCompareKeepResults = 'gitlens:views:searchAndCompare:keepResults', Vsls = 'gitlens:vsls', - Premium = 'gitlens:premium', - PremiumAllowed = 'gitlens:plus:allowed', - PremiumRequired = 'gitlens:plus:required', - PremiumState = 'gitlens:plus:state', + Plus = 'gitlens:plus', + PlusAllowed = 'gitlens:plus:allowed', + PlusRequired = 'gitlens:plus:required', + PlusState = 'gitlens:plus:state', } export const enum CoreCommands { diff --git a/src/env/node/git/localGitProvider.ts b/src/env/node/git/localGitProvider.ts index 954caae..c60d7fd 100644 --- a/src/env/node/git/localGitProvider.ts +++ b/src/env/node/git/localGitProvider.ts @@ -26,7 +26,7 @@ import type { import { configuration } from '../../../configuration'; import { CoreGitConfiguration, GlyphChars, Schemes } from '../../../constants'; import type { Container } from '../../../container'; -import { Features, PremiumFeatures } from '../../../features'; +import { Features, PlusFeatures } from '../../../features'; import { StashApplyError, StashApplyErrorReason, @@ -397,8 +397,8 @@ export class LocalGitProvider implements GitProvider, Disposable { }; } - private _allowedFeatures = new Map>(); - async allows(feature: PremiumFeatures, plan: SubscriptionPlanId, repoPath?: string): Promise { + private _allowedFeatures = new Map>(); + async allows(feature: PlusFeatures, plan: SubscriptionPlanId, repoPath?: string): Promise { if (plan === SubscriptionPlanId.Free) return false; if (plan === SubscriptionPlanId.Pro) return true; @@ -416,7 +416,7 @@ export class LocalGitProvider implements GitProvider, Disposable { ? true : (await this.visibility(repoPath)) === RepositoryVisibility.Public; if (allowedByRepo == null) { - allowedByRepo = new Map(); + allowedByRepo = new Map(); this._allowedFeatures.set(repoPath, allowedByRepo); } diff --git a/src/features.ts b/src/features.ts index a7a5c83..d7a5793 100644 --- a/src/features.ts +++ b/src/features.ts @@ -10,7 +10,7 @@ export type FeatureAccess = | { allowed: true; subscription: { current: Subscription; required?: undefined } } | { allowed: false; subscription: { current: Subscription; required?: RequiredSubscriptionPlans } }; -export const enum PremiumFeatures { +export const enum PlusFeatures { Timeline = 'timeline', Worktrees = 'worktrees', } diff --git a/src/git/gitProvider.ts b/src/git/gitProvider.ts index 29b435c..1a1f900 100644 --- a/src/git/gitProvider.ts +++ b/src/git/gitProvider.ts @@ -1,6 +1,6 @@ import { Disposable, Event, Range, TextDocument, Uri, WorkspaceFolder } from 'vscode'; import type { Commit, InputBox } from '../@types/vscode.git'; -import { Features, PremiumFeatures } from '../features'; +import { Features, PlusFeatures } from '../features'; import type { SubscriptionPlanId } from '../subscription'; import type { GitUri } from './gitUri'; import type { @@ -115,7 +115,7 @@ export interface GitProvider extends Disposable { ): Repository; openRepositoryInitWatcher?(): RepositoryInitWatcher; - allows(feature: PremiumFeatures, plan: SubscriptionPlanId, repoPath?: string): Promise; + allows(feature: PlusFeatures, plan: SubscriptionPlanId, repoPath?: string): Promise; supports(feature: Features): Promise; visibility(repoPath: string): Promise; diff --git a/src/git/gitProviderService.ts b/src/git/gitProviderService.ts index 75b744f..4e840f8 100644 --- a/src/git/gitProviderService.ts +++ b/src/git/gitProviderService.ts @@ -21,7 +21,7 @@ import { ContextKeys, CoreGitConfiguration, GlyphChars, Schemes } from '../const import type { Container } from '../container'; import { setContext } from '../context'; import { AccessDeniedError, ProviderNotFoundError } from '../errors'; -import type { FeatureAccess, Features, PremiumFeatures } from '../features'; +import type { FeatureAccess, Features, PlusFeatures } from '../features'; import { Logger } from '../logger'; import type { SubscriptionChangeEvent } from '../premium/subscription/subscriptionService'; import { asRepoComparisonKey, RepoComparisionKey, Repositories } from '../repositories'; @@ -126,7 +126,7 @@ export const enum RepositoriesVisibility { } export class GitProviderService implements Disposable { - static readonly previewFeatures: Map | undefined; // = new Map(); + static readonly previewFeatures: Map | undefined; // = new Map(); private readonly _onDidChangeProviders = new EventEmitter(); get onDidChangeProviders(): Event { @@ -533,7 +533,7 @@ export class GitProviderService implements Disposable { } private _accessCache = new Map>(); - async access(feature?: PremiumFeatures, repoPath?: string | Uri): Promise { + async access(feature?: PlusFeatures, repoPath?: string | Uri): Promise { let cacheKey; if (repoPath != null) { const { path } = this.getProvider(repoPath); @@ -549,7 +549,7 @@ export class GitProviderService implements Disposable { } @debug() - private async accessCore(feature?: PremiumFeatures, repoPath?: string | Uri): Promise { + private async accessCore(feature?: PlusFeatures, repoPath?: string | Uri): Promise { const subscription = await this.getSubscription(); if (subscription.account?.verified === false) { return { allowed: false, subscription: { current: subscription } }; @@ -630,7 +630,7 @@ export class GitProviderService implements Disposable { return getRepoAccess.call(this, repoPath, plan); } - async ensureAccess(feature: PremiumFeatures, repoPath?: string): Promise { + async ensureAccess(feature: PlusFeatures, repoPath?: string): Promise { const { allowed, subscription } = await this.access(feature, repoPath); if (!allowed) throw new AccessDeniedError(subscription.current, subscription.required); } diff --git a/src/git/models/repository.ts b/src/git/models/repository.ts index d831e86..bd1d70e 100644 --- a/src/git/models/repository.ts +++ b/src/git/models/repository.ts @@ -14,7 +14,7 @@ import type { CreatePullRequestActionContext } from '../../api/gitlens'; import { configuration } from '../../configuration'; import { CoreGitCommands, CoreGitConfiguration, Schemes } from '../../constants'; import { Container } from '../../container'; -import type { FeatureAccess, Features, PremiumFeatures } from '../../features'; +import type { FeatureAccess, Features, PlusFeatures } from '../../features'; import { Logger } from '../../logger'; import { Messages } from '../../messages'; import { asRepoComparisonKey } from '../../repositories'; @@ -400,7 +400,7 @@ export class Repository implements Disposable { } @log() - access(feature?: PremiumFeatures): Promise { + access(feature?: PlusFeatures): Promise { return this.container.git.access(feature, this.uri); } diff --git a/src/premium/github/githubGitProvider.ts b/src/premium/github/githubGitProvider.ts index 747adb2..bd372a5 100644 --- a/src/premium/github/githubGitProvider.ts +++ b/src/premium/github/githubGitProvider.ts @@ -25,7 +25,7 @@ import { OpenVirtualRepositoryError, OpenVirtualRepositoryErrorReason, } from '../../errors'; -import { Features, PremiumFeatures } from '../../features'; +import { Features, PlusFeatures } from '../../features'; import { GitProvider, GitProviderId, @@ -188,8 +188,8 @@ export class GitHubGitProvider implements GitProvider, Disposable { ); } - private _allowedFeatures = new Map>(); - async allows(feature: PremiumFeatures, plan: SubscriptionPlanId, repoPath?: string): Promise { + private _allowedFeatures = new Map>(); + async allows(feature: PlusFeatures, plan: SubscriptionPlanId, repoPath?: string): Promise { if (plan === SubscriptionPlanId.Free) return false; if (plan === SubscriptionPlanId.Pro) return true; @@ -207,7 +207,7 @@ export class GitHubGitProvider implements GitProvider, Disposable { ? true : (await this.visibility(repoPath)) === RepositoryVisibility.Public; if (allowedByRepo == null) { - allowedByRepo = new Map(); + allowedByRepo = new Map(); this._allowedFeatures.set(repoPath, allowedByRepo); } diff --git a/src/premium/subscription/authenticationProvider.ts b/src/premium/subscription/authenticationProvider.ts index 054742f..10e432b 100644 --- a/src/premium/subscription/authenticationProvider.ts +++ b/src/premium/subscription/authenticationProvider.ts @@ -24,9 +24,9 @@ interface StoredSession { scopes: string[]; } -const authenticationId = 'gitlens-gitkraken'; -const authenticationLabel = 'GitKraken'; -const authenticationSecretKey = `gitkraken.auth`; +const authenticationId = 'gitlens+'; +const authenticationLabel = 'GitLens+'; +const authenticationSecretKey = `gitlens.plus.auth`; export class SubscriptionAuthenticationProvider implements AuthenticationProvider, Disposable { private _onDidChangeSessions = new EventEmitter(); @@ -82,7 +82,7 @@ export class SubscriptionAuthenticationProvider implements AuthenticationProvide if (ex === 'Cancelled') throw ex; Logger.error(ex, cc); - void window.showErrorMessage(`Unable to sign in: ${ex}`); + void window.showErrorMessage(`Unable to sign in to GitLens+: ${ex}`); throw ex; } } diff --git a/src/premium/subscription/subscriptionService.ts b/src/premium/subscription/subscriptionService.ts index f5c187d..2504617 100644 --- a/src/premium/subscription/subscriptionService.ts +++ b/src/premium/subscription/subscriptionService.ts @@ -47,7 +47,7 @@ import { memoize } from '../../system/decorators/memoize'; import { once } from '../../system/function'; import { pluralize } from '../../system/string'; import { openWalkthrough } from '../../system/utils'; -import { ensurePremiumFeaturesEnabled } from './utils'; +import { ensurePlusFeaturesEnabled } from './utils'; // TODO: What user-agent should we use? const userAgent = 'Visual-Studio-Code-GitLens'; @@ -59,7 +59,7 @@ export interface SubscriptionChangeEvent { } export class SubscriptionService implements Disposable { - private static authenticationProviderId = 'gitlens-gitkraken'; + private static authenticationProviderId = 'gitlens+'; private static authenticationScopes = ['gitlens']; private _onDidChange = new EventEmitter(); @@ -161,24 +161,24 @@ export class SubscriptionService implements Disposable { void this.container.viewCommands; return [ - commands.registerCommand(Commands.PremiumLearn, openToSide => this.learn(openToSide)), - commands.registerCommand(Commands.PremiumLoginOrSignUp, () => this.loginOrSignUp()), - commands.registerCommand(Commands.PremiumLogout, () => this.logout()), + commands.registerCommand(Commands.PlusLearn, openToSide => this.learn(openToSide)), + commands.registerCommand(Commands.PlusLoginOrSignUp, () => this.loginOrSignUp()), + commands.registerCommand(Commands.PlusLogout, () => this.logout()), - commands.registerCommand(Commands.PremiumStartPreviewTrial, () => this.startPreviewTrial()), - commands.registerCommand(Commands.PremiumManage, () => this.manage()), - commands.registerCommand(Commands.PremiumPurchase, () => this.purchase()), + commands.registerCommand(Commands.PlusStartPreviewTrial, () => this.startPreviewTrial()), + commands.registerCommand(Commands.PlusManage, () => this.manage()), + commands.registerCommand(Commands.PlusPurchase, () => this.purchase()), - commands.registerCommand(Commands.PremiumResendVerification, () => this.resendVerification()), - commands.registerCommand(Commands.PremiumValidate, () => this.validate()), + commands.registerCommand(Commands.PlusResendVerification, () => this.resendVerification()), + commands.registerCommand(Commands.PlusValidate, () => this.validate()), - commands.registerCommand(Commands.PremiumShowPlans, () => this.showPlans()), + commands.registerCommand(Commands.PlusShowPlans, () => this.showPlans()), - commands.registerCommand(Commands.PremiumHide, () => - configuration.updateEffective('premiumFeatures.enabled', false), + commands.registerCommand(Commands.PlusHide, () => + configuration.updateEffective('plusFeatures.enabled', false), ), - commands.registerCommand(Commands.PremiumRestore, () => - configuration.updateEffective('premiumFeatures.enabled', true), + commands.registerCommand(Commands.PlusRestore, () => + configuration.updateEffective('plusFeatures.enabled', true), ), commands.registerCommand('gitlens.plus.reset', () => this.logout(true)), @@ -198,7 +198,7 @@ export class SubscriptionService implements Disposable { @gate() @log() async loginOrSignUp(): Promise { - if (!(await ensurePremiumFeaturesEnabled())) return false; + if (!(await ensurePlusFeaturesEnabled())) return false; void this.showHomeView(); @@ -209,7 +209,7 @@ export class SubscriptionService implements Disposable { if (loggedIn) { const { account, - plan: { actual }, + plan: { actual, effective }, } = this._subscription; if (account?.verified === false) { @@ -232,10 +232,9 @@ export class SubscriptionService implements Disposable { const result = await window.showInformationMessage( `You are now signed in to your ${ actual.name - } account which gives you access to premium features for public repos.\n\nYou were also granted a trial of premium features for both public and private repos for ${pluralize( - 'more day', - remaining ?? 0, - )}.`, + } account which gives you access to GitLens+ features on public repos.\n\nYou were also granted a trial of ${ + effective.name + } for both public and private repos for ${pluralize('more day', remaining ?? 0)}.`, { modal: true }, confirm, learn, @@ -281,7 +280,7 @@ export class SubscriptionService implements Disposable { @log() async purchase(): Promise { - if (!(await ensurePremiumFeaturesEnabled())) return; + if (!(await ensurePlusFeaturesEnabled())) return; if (this._subscription.account == null) { void this.showPlans(); @@ -345,7 +344,7 @@ export class SubscriptionService implements Disposable { @log() async showHomeView(silent: boolean = false): Promise { - if (silent && !configuration.get('premiumFeatures.enabled', undefined, true)) return; + if (silent && !configuration.get('plusFeatures.enabled', undefined, true)) return; if (!this.container.homeView.visible) { await executeCommand(Commands.ShowHomeView); @@ -359,17 +358,17 @@ export class SubscriptionService implements Disposable { @gate() @log() async startPreviewTrial(): Promise { - if (!(await ensurePremiumFeaturesEnabled())) return; + if (!(await ensurePlusFeaturesEnabled())) return; let { plan, previewTrial } = this._subscription; if (previewTrial != null || plan.effective.id !== SubscriptionPlanId.Free) { void this.showHomeView(); if (plan.effective.id === SubscriptionPlanId.Free) { - const confirm: MessageItem = { title: 'Sign In', isCloseAffordance: true }; + const confirm: MessageItem = { title: 'Sign in to GitLens+', isCloseAffordance: true }; const cancel: MessageItem = { title: 'Cancel' }; const result = await window.showInformationMessage( - 'Your GitLens premium features trial has ended.\nPlease sign in to use premium features on public repos and get a free 7-day trial for both public and private repos.', + 'Your GitLens+ features trial has ended.\nPlease sign in to use GitLens+ features on public repos and get a free 7-day trial for both public and private repos.', { modal: true }, confirm, cancel, @@ -413,7 +412,7 @@ export class SubscriptionService implements Disposable { const confirm: MessageItem = { title: 'OK', isCloseAffordance: true }; const learn: MessageItem = { title: 'Learn More' }; const result = await window.showInformationMessage( - `You have started a ${days} day trial of GitLens premium features for both public and private repos.`, + `You have started a ${days} day trial of GitLens+ features for both public and private repos.`, { modal: true }, confirm, learn, @@ -642,7 +641,7 @@ export class SubscriptionService implements Disposable { if (createIfNeeded) { void window.showErrorMessage( - `Unable to sign in to your account. Please try again. If this issue persists, please contact support. Account=${name} Error=${ex.message}`, + `Unable to sign in to your GitLens+ account. Please try again. If this issue persists, please contact support. Account=${name} Error=${ex.message}`, 'OK', ); } @@ -702,12 +701,12 @@ export class SubscriptionService implements Disposable { } private getStoredSubscription(): Subscription | undefined { - const storedSubscription = this.container.storage.get>(StorageKeys.PremiumSubscription); + const storedSubscription = this.container.storage.get>(StorageKeys.Subscription); return storedSubscription?.data; } private async storeSubscription(subscription: Subscription): Promise { - return this.container.storage.store>(StorageKeys.PremiumSubscription, { + return this.container.storage.store>(StorageKeys.Subscription, { v: 1, data: subscription, }); @@ -723,8 +722,8 @@ export class SubscriptionService implements Disposable { : subscription.required != null && isSubscriptionPaidPlan(subscription.required) ? 'paid' : 'free+'; - void setContext(ContextKeys.PremiumAllowed, allowed); - void setContext(ContextKeys.PremiumRequired, required); + void setContext(ContextKeys.PlusAllowed, allowed); + void setContext(ContextKeys.PlusRequired, required); }); const { @@ -732,8 +731,8 @@ export class SubscriptionService implements Disposable { state, } = this._subscription; - void setContext(ContextKeys.Premium, actual.id != SubscriptionPlanId.Free ? actual.id : undefined); - void setContext(ContextKeys.PremiumState, state); + void setContext(ContextKeys.Plus, actual.id != SubscriptionPlanId.Free ? actual.id : undefined); + void setContext(ContextKeys.PlusState, state); } private updateStatusBar(): void { @@ -772,7 +771,7 @@ export class SubscriptionService implements Disposable { this._statusBarSubscription.tooltip = new MarkdownString( trial ? `**Please verify your email**\n\nBefore you can start your **${effective.name}** trial, please verify the email for the account you created.\n\nClick for details` - : `**Please verify your email**\n\nBefore you use premium GitLens features, please verify the email for the account you created.\n\nClick for details`, + : `**Please verify your email**\n\nBefore you can use GitLens+ features, please verify the email for the account you created.\n\nClick for details`, true, ); } else { @@ -782,7 +781,7 @@ export class SubscriptionService implements Disposable { this._statusBarSubscription.tooltip = new MarkdownString( `You are currently trialing **${ effective.name - }**, which gives you access to premium GitLens features. You have ${pluralize( + }**, which gives you access to GitLens+ features on both public and private repos. You have ${pluralize( 'day', remaining ?? 0, )} remaining in your trial.\n\nClick for details`, diff --git a/src/premium/subscription/utils.ts b/src/premium/subscription/utils.ts index 2420d5a..00dcb62 100644 --- a/src/premium/subscription/utils.ts +++ b/src/premium/subscription/utils.ts @@ -1,13 +1,13 @@ import { MessageItem, window } from 'vscode'; import { configuration } from '../../configuration'; -export async function ensurePremiumFeaturesEnabled(): Promise { - if (configuration.get('premiumFeatures.enabled', undefined, true)) return true; +export async function ensurePlusFeaturesEnabled(): Promise { + if (configuration.get('plusFeatures.enabled', undefined, true)) return true; const confirm: MessageItem = { title: 'Enable' }; const cancel: MessageItem = { title: 'Cancel', isCloseAffordance: true }; const result = await window.showInformationMessage( - 'Premium features are currently disabled. Would you like to enable them?', + 'GitLens+ features are currently disabled. Would you like to enable them?', { modal: true }, confirm, cancel, @@ -15,6 +15,6 @@ export async function ensurePremiumFeaturesEnabled(): Promise { if (result !== confirm) return false; - void (await configuration.updateEffective('premiumFeatures.enabled', true)); + void (await configuration.updateEffective('plusFeatures.enabled', true)); return true; } diff --git a/src/premium/webviews/timeline/timelineWebview.ts b/src/premium/webviews/timeline/timelineWebview.ts index 5bdf4bd..280c987 100644 --- a/src/premium/webviews/timeline/timelineWebview.ts +++ b/src/premium/webviews/timeline/timelineWebview.ts @@ -5,7 +5,7 @@ import { configuration } from '../../../configuration'; import { Commands, ContextKeys } from '../../../constants'; import type { Container } from '../../../container'; import { setContext } from '../../../context'; -import { PremiumFeatures } from '../../../features'; +import { PlusFeatures } from '../../../features'; import { GitUri } from '../../../git/gitUri'; import { RepositoryChange, RepositoryChangeComparisonMode, RepositoryChangeEvent } from '../../../git/models'; import { createFromDateDelta } from '../../../system/date'; @@ -16,7 +16,7 @@ import { hasVisibleTextEditor, isTextEditor } from '../../../system/utils'; import { IpcMessage, onIpc } from '../../../webviews/protocol'; import { WebviewBase } from '../../../webviews/webviewBase'; import type { SubscriptionChangeEvent } from '../../subscription/subscriptionService'; -import { ensurePremiumFeaturesEnabled } from '../../subscription/utils'; +import { ensurePlusFeaturesEnabled } from '../../subscription/utils'; import { Commit, DidChangeStateNotificationType, @@ -63,7 +63,7 @@ export class TimelineWebview extends WebviewBase { } override async show(column: ViewColumn = ViewColumn.Beside): Promise { - if (!(await ensurePremiumFeaturesEnabled())) return; + if (!(await ensurePlusFeaturesEnabled())) return; return super.show(column); } @@ -202,7 +202,7 @@ export class TimelineWebview extends WebviewBase { @debug({ args: false }) private async getState(current: Context): Promise { - const access = await this.container.git.access(PremiumFeatures.Timeline); + const access = await this.container.git.access(PlusFeatures.Timeline); const dateFormat = this.container.config.defaultDateFormat ?? 'MMMM Do, YYYY h:mma'; const period = current.period ?? defaultPeriod; diff --git a/src/premium/webviews/timeline/timelineWebviewView.ts b/src/premium/webviews/timeline/timelineWebviewView.ts index df2ee0c..f4bdbf8 100644 --- a/src/premium/webviews/timeline/timelineWebviewView.ts +++ b/src/premium/webviews/timeline/timelineWebviewView.ts @@ -4,7 +4,7 @@ import type { ShowQuickCommitCommandArgs } from '../../../commands'; import { configuration } from '../../../configuration'; import { Commands } from '../../../constants'; import { Container } from '../../../container'; -import { PremiumFeatures } from '../../../features'; +import { PlusFeatures } from '../../../features'; import type { RepositoriesChangeEvent } from '../../../git/gitProviderService'; import { GitUri } from '../../../git/gitUri'; import { RepositoryChange, RepositoryChangeComparisonMode, RepositoryChangeEvent } from '../../../git/models'; @@ -16,7 +16,7 @@ import { hasVisibleTextEditor, isTextEditor } from '../../../system/utils'; import { IpcMessage, onIpc } from '../../../webviews/protocol'; import { WebviewViewBase } from '../../../webviews/webviewViewBase'; import type { SubscriptionChangeEvent } from '../../subscription/subscriptionService'; -import { ensurePremiumFeaturesEnabled } from '../../subscription/utils'; +import { ensurePlusFeaturesEnabled } from '../../subscription/utils'; import { Commit, DidChangeStateNotificationType, @@ -56,7 +56,7 @@ export class TimelineWebviewView extends WebviewViewBase { } override async show(options?: { preserveFocus?: boolean | undefined }): Promise { - if (!(await ensurePremiumFeaturesEnabled())) return; + if (!(await ensurePlusFeaturesEnabled())) return; return super.show(options); } @@ -195,7 +195,7 @@ export class TimelineWebviewView extends WebviewViewBase { @debug({ args: false }) private async getState(current: Context): Promise { - const access = await this.container.git.access(PremiumFeatures.Timeline); + const access = await this.container.git.access(PlusFeatures.Timeline); const dateFormat = this.container.config.defaultDateFormat ?? 'MMMM Do, YYYY h:mma'; const period = current.period ?? defaultPeriod; diff --git a/src/quickpicks/items/directive.ts b/src/quickpicks/items/directive.ts index 6b94956..cab4e80 100644 --- a/src/quickpicks/items/directive.ts +++ b/src/quickpicks/items/directive.ts @@ -46,21 +46,21 @@ export namespace DirectiveQuickPickItem { label = 'Try again'; break; case Directive.StartPreviewTrial: - label = 'Try Premium Features Now'; - detail = 'Try premium features now, without an account, for 3 days'; + label = 'Try GitLens+ Features Now'; + detail = 'Try GitLens+ features now, without an account, for 3 days'; break; case Directive.RequiresVerification: label = 'Resend Verification Email'; detail = 'You must verify your account email address before you can continue'; break; case Directive.RequiresFreeSubscription: - label = 'Sign In'; + label = 'Sign in to GitLens+'; detail = - 'To use premium features on public repos and get a free 7-day trial for both public and private repos'; + 'To use GitLens+ features on public repos and get a free 7-day trial for both public and private repos'; break; case Directive.RequiresPaidSubscription: label = 'Upgrade your account'; - detail = 'To use premium features on both public and private repos'; + detail = 'To use GitLens+ features on both public and private repos'; break; } } diff --git a/src/storage.ts b/src/storage.ts index ded0826..04fe77d 100644 --- a/src/storage.ts +++ b/src/storage.ts @@ -74,8 +74,7 @@ export const enum StorageKeys { PendingWhatsNewOnFocus = 'gitlens:pendingWhatsNewOnFocus', Version = 'gitlens:version', - PremiumSubscription = 'gitlens:plus:subscription', - PremiumPreview = 'gitlens:plus:preview', + Subscription = 'gitlens:premium:subscription', // Don't change this key name as its the stored subscription Deprecated_Version = 'gitlensVersion', } diff --git a/src/subscription.ts b/src/subscription.ts index b42cde6..bf82bd5 100644 --- a/src/subscription.ts +++ b/src/subscription.ts @@ -114,16 +114,16 @@ export function getSubscriptionPlan(id: SubscriptionPlanId, startedOn?: Date, ex export function getSubscriptionPlanName(id: SubscriptionPlanId) { switch (id) { case SubscriptionPlanId.FreePlus: - return 'GitLens Free+'; + return 'GitLens+'; case SubscriptionPlanId.Pro: - return 'GitLens Pro'; + return 'GitLens+ Pro'; case SubscriptionPlanId.Teams: - return 'GitLens Teams'; + return 'GitLens+ Teams'; case SubscriptionPlanId.Enterprise: - return 'GitLens Enterprise'; + return 'GitLens+ Enterprise'; case SubscriptionPlanId.Free: default: - return 'GitLens Free'; + return 'GitLens'; } } diff --git a/src/views/nodes/worktreesNode.ts b/src/views/nodes/worktreesNode.ts index a6a2cef..62028bf 100644 --- a/src/views/nodes/worktreesNode.ts +++ b/src/views/nodes/worktreesNode.ts @@ -1,6 +1,6 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; import { GlyphChars } from '../../constants'; -import { PremiumFeatures } from '../../features'; +import { PlusFeatures } from '../../features'; import { GitUri } from '../../git/gitUri'; import { Repository } from '../../git/models'; import { gate } from '../../system/decorators/gate'; @@ -39,7 +39,7 @@ export class WorktreesNode extends ViewNode { async getChildren(): Promise { if (this._children == null) { - const access = await this.repo.access(PremiumFeatures.Worktrees); + const access = await this.repo.access(PlusFeatures.Worktrees); if (!access.allowed) return []; const worktrees = await this.repo.getWorktrees(); @@ -52,7 +52,7 @@ export class WorktreesNode extends ViewNode { } async getTreeItem(): Promise { - const access = await this.repo.access(PremiumFeatures.Worktrees); + const access = await this.repo.access(PlusFeatures.Worktrees); const item = new TreeItem( 'Worktrees', @@ -62,7 +62,7 @@ export class WorktreesNode extends ViewNode { item.contextValue = ContextValues.Worktrees; item.description = access.allowed ? undefined - : ` ${GlyphChars.Warning} Premium feature which requires an account`; + : ` ${GlyphChars.Warning} GitLens+ feature which requires an account`; // TODO@eamodio `folder` icon won't work here for some reason item.iconPath = new ThemeIcon('folder-opened'); return item; diff --git a/src/views/worktreesView.ts b/src/views/worktreesView.ts index 22a69d5..7b1c47e 100644 --- a/src/views/worktreesView.ts +++ b/src/views/worktreesView.ts @@ -12,10 +12,10 @@ import { } from 'vscode'; import { configuration, ViewFilesLayout, ViewShowBranchComparison, WorktreesViewConfig } from '../configuration'; import { Container } from '../container'; -import { PremiumFeatures } from '../features'; +import { PlusFeatures } from '../features'; import { GitUri } from '../git/gitUri'; import { GitWorktree, RepositoryChange, RepositoryChangeComparisonMode, RepositoryChangeEvent } from '../git/models'; -import { ensurePremiumFeaturesEnabled } from '../premium/subscription/utils'; +import { ensurePlusFeaturesEnabled } from '../premium/subscription/utils'; import { getSubscriptionTimeRemaining, SubscriptionState } from '../subscription'; import { gate } from '../system/decorators/gate'; import { pluralize } from '../system/string'; @@ -50,7 +50,7 @@ export class WorktreesRepositoryNode extends RepositoryFolderNode { async getChildren(): Promise { - const access = await this.view.container.git.access(PremiumFeatures.Worktrees); + const access = await this.view.container.git.access(PlusFeatures.Worktrees); if (!access.allowed) return []; if (this.children == null) { @@ -129,7 +129,7 @@ export class WorktreesView extends ViewBase { - if (!(await ensurePremiumFeaturesEnabled())) return; + if (!(await ensurePlusFeaturesEnabled())) return; return super.show(options); } @@ -154,7 +154,7 @@ export class WorktreesView extends ViewBaseWalkthrough
  • - Premium features walkthrough + GitLens+ features walkthrough
  • -

    Continue using Premium Features

    +

    Continue using GitLens+ Features

    Your - premium features trial - has ended. Don't worry, non-premium features are always accessible. + GitLens+ features trial + has ended. Don't worry, all other GitLens features are always accessible.

    - Sign in to use premium features on public repos and get an additional 7-day free trial for both - public and private repos. + Sign in to use GitLens+ features on public repos and get an additional 7-day free trial for both public and + private repos.

    - Sign in + Sign in to GitLens+

    Or, upgrade your account to use - premium features on both public and private repos. + GitLens+ features on both public and private repos.

    -

    Premium Features (Optional)

    - Premium features are - all-new, completely optional, features that enhance your current GitLens experience when you sign with an - account. -

    -

    -  Non-premium features are always accessible, without an account, - and will continue to evolve and be invested in. -

    -

    Visual File History

    - Visual File History screenshot -

    - The - Visual File HistoryLearn more about GitLens+ features - allows you to quickly see the evolution of a file, including when changes were made, how large they were, - and who made them.

    -

    Worktrees

    - Worktrees screenshot -

    - Worktrees - allow you to easily work on different branches of a repository simultaneously. +

    +  All other GitLens features are always accessible, without an + account, and will continue to evolve and be invested in.

    diff --git a/src/webviews/apps/home/partials/state.free-preview.html b/src/webviews/apps/home/partials/state.free-preview.html index 315ad61..9d33de6 100644 --- a/src/webviews/apps/home/partials/state.free-preview.html +++ b/src/webviews/apps/home/partials/state.free-preview.html @@ -1,26 +1,27 @@