diff --git a/src/plus/webviews/graph/graphWebview.ts b/src/plus/webviews/graph/graphWebview.ts index f0ecc3b..c9c406c 100644 --- a/src/plus/webviews/graph/graphWebview.ts +++ b/src/plus/webviews/graph/graphWebview.ts @@ -59,6 +59,7 @@ export class GraphWebview extends WebviewBase { 'graph.html', 'images/gitlens-icon.png', 'Commit Graph', + 'graphWebview', Commands.ShowGraphPage, ); this.disposables.push(configuration.onDidChange(this.onConfigurationChanged, this), { @@ -74,8 +75,6 @@ export class GraphWebview extends WebviewBase { override async show(column: ViewColumn = ViewColumn.Active, ...args: any[]): Promise { if (!(await ensurePlusFeaturesEnabled())) return; - void this.container.usage.track('graphWebview:shown'); - if (this.container.git.repositoryCount > 1) { const [contexts] = parseCommandContext(Commands.ShowGraphPage, undefined, ...args); const context = Array.isArray(contexts) ? contexts[0] : contexts; diff --git a/src/plus/webviews/timeline/timelineWebview.ts b/src/plus/webviews/timeline/timelineWebview.ts index 13a00bf..c0eb08f 100644 --- a/src/plus/webviews/timeline/timelineWebview.ts +++ b/src/plus/webviews/timeline/timelineWebview.ts @@ -49,6 +49,7 @@ export class TimelineWebview extends WebviewBase { 'timeline.html', 'images/gitlens-icon.png', 'Visual File History', + 'timelineWebview', Commands.ShowTimelinePage, ); this._context = { @@ -62,7 +63,6 @@ export class TimelineWebview extends WebviewBase { override async show(column: ViewColumn = ViewColumn.Beside, ...args: any[]): Promise { if (!(await ensurePlusFeaturesEnabled())) return; - void this.container.usage.track('timelineWebview:shown'); return super.show(column, ...args); } diff --git a/src/plus/webviews/timeline/timelineWebviewView.ts b/src/plus/webviews/timeline/timelineWebviewView.ts index 12ba238..893b97e 100644 --- a/src/plus/webviews/timeline/timelineWebviewView.ts +++ b/src/plus/webviews/timeline/timelineWebviewView.ts @@ -43,7 +43,7 @@ export class TimelineWebviewView extends WebviewViewBase { private _pendingContext: Partial | undefined; constructor(container: Container) { - super(container, 'gitlens.views.timeline', 'timeline.html', 'Visual File History'); + super(container, 'gitlens.views.timeline', 'timeline.html', 'Visual File History', 'timelineView'); this._context = { uri: undefined, @@ -57,7 +57,6 @@ export class TimelineWebviewView extends WebviewViewBase { override async show(options?: { preserveFocus?: boolean | undefined }): Promise { if (!(await ensurePlusFeaturesEnabled())) return; - void this.container.usage.track('timelineView:shown'); return super.show(options); } diff --git a/src/usageTracker.ts b/src/usageTracker.ts index e136fda..808d21e 100644 --- a/src/usageTracker.ts +++ b/src/usageTracker.ts @@ -8,7 +8,27 @@ export interface TrackedUsage { firstUsedAt: number; lastUsedAt: number; } -export type TrackedUsageKeys = 'graphWebview:shown' | 'timelineWebview:shown' | 'timelineView:shown'; + +export type TrackedUsageFeatures = + | 'branchesView' + | 'commitDetailsView' + | 'commitsView' + | 'contributorsView' + | 'fileHistoryView' + | 'graphWebview' + | 'homeView' + | 'lineHistoryView' + | 'remotesView' + | 'repositoriesView' + | 'stashesView' + | 'settingsWebview' + | 'searchAndCompareView' + | 'tagsView' + | 'timelineWebview' + | 'timelineView' + | 'welcomeWebview' + | 'workspaceView'; +export type TrackedUsageKeys = `${TrackedUsageFeatures}:shown`; export type UsageChangeEvent = { /** diff --git a/src/views/branchesView.ts b/src/views/branchesView.ts index 180c85f..e40f9ec 100644 --- a/src/views/branchesView.ts +++ b/src/views/branchesView.ts @@ -97,7 +97,7 @@ export class BranchesView extends ViewBase protected readonly configKey = 'branches'; constructor(container: Container) { - super('gitlens.views.branches', 'Branches', container); + super(container, 'gitlens.views.branches', 'Branches', 'branchesView'); } override get canReveal(): boolean { diff --git a/src/views/commitsView.ts b/src/views/commitsView.ts index 28c7b78..749b9f2 100644 --- a/src/views/commitsView.ts +++ b/src/views/commitsView.ts @@ -178,7 +178,7 @@ export class CommitsView extends ViewBase { protected readonly configKey = 'commits'; constructor(container: Container) { - super('gitlens.views.commits', 'Commits', container); + super(container, 'gitlens.views.commits', 'Commits', 'commitsView'); this.disposables.push(container.usage.onDidChange(this.onUsageChanged, this)); } diff --git a/src/views/contributorsView.ts b/src/views/contributorsView.ts index 2df464d..30d424c 100644 --- a/src/views/contributorsView.ts +++ b/src/views/contributorsView.ts @@ -115,7 +115,7 @@ export class ContributorsView extends ViewBase { protected readonly configKey = 'remotes'; constructor(container: Container) { - super('gitlens.views.remotes', 'Remotes', container); + super(container, 'gitlens.views.remotes', 'Remotes', 'remotesView'); } override get canReveal(): boolean { diff --git a/src/views/repositoriesView.ts b/src/views/repositoriesView.ts index 90d9391..5e6be41 100644 --- a/src/views/repositoriesView.ts +++ b/src/views/repositoriesView.ts @@ -44,7 +44,7 @@ export class RepositoriesView extends ViewBase(); diff --git a/src/views/searchAndCompareView.ts b/src/views/searchAndCompareView.ts index f9bc1b5..20603da 100644 --- a/src/views/searchAndCompareView.ts +++ b/src/views/searchAndCompareView.ts @@ -247,7 +247,7 @@ export class SearchAndCompareView extends ViewBase { protected readonly configKey = 'stashes'; constructor(container: Container) { - super('gitlens.views.stashes', 'Stashes', container); + super(container, 'gitlens.views.stashes', 'Stashes', 'stashesView'); } override get canReveal(): boolean { diff --git a/src/views/tagsView.ts b/src/views/tagsView.ts index 6bf285d..9a1a7ca 100644 --- a/src/views/tagsView.ts +++ b/src/views/tagsView.ts @@ -85,7 +85,7 @@ export class TagsView extends ViewBase { protected readonly configKey = 'tags'; constructor(container: Container) { - super('gitlens.views.tags', 'Tags', container); + super(container, 'gitlens.views.tags', 'Tags', 'tagsView'); } override get canReveal(): boolean { diff --git a/src/views/viewBase.ts b/src/views/viewBase.ts index a3255b5..d148e5f 100644 --- a/src/views/viewBase.ts +++ b/src/views/viewBase.ts @@ -33,6 +33,7 @@ import { debug, getLogScope, log } from '../system/decorators/log'; import { once } from '../system/event'; import { debounce } from '../system/function'; import { cancellable, isPromise } from '../system/promise'; +import type { TrackedUsageFeatures } from '../usageTracker'; import type { BranchesView } from './branchesView'; import type { CommitsView } from './commitsView'; import type { ContributorsView } from './contributorsView'; @@ -109,9 +110,10 @@ export abstract class ViewBase< private readonly _lastKnownLimits = new Map(); constructor( + public readonly container: Container, public readonly id: `gitlens.views.${string}`, public readonly name: string, - public readonly container: Container, + private readonly trackingFeature: TrackedUsageFeatures, ) { this.disposables.push(once(container.onReady)(this.onReady, this)); @@ -315,6 +317,10 @@ export abstract class ViewBase< } protected onVisibilityChanged(e: TreeViewVisibilityChangeEvent) { + if (e.visible) { + void this.container.usage.track(`${this.trackingFeature}:shown`); + } + this._onDidChangeVisibility.fire(e); } diff --git a/src/views/worktreesView.ts b/src/views/worktreesView.ts index 50c0c81..dddb7e3 100644 --- a/src/views/worktreesView.ts +++ b/src/views/worktreesView.ts @@ -96,7 +96,7 @@ export class WorktreesView extends ViewBase { constructor(container: Container) { - super(container, 'gitlens.views.home', 'home.html', 'Home'); + super(container, 'gitlens.views.home', 'home.html', 'Home', 'homeView'); this.disposables.push(this.container.subscription.onDidChange(this.onSubscriptionChanged, this)); } diff --git a/src/webviews/settings/settingsWebview.ts b/src/webviews/settings/settingsWebview.ts index cf998cc..1449ac9 100644 --- a/src/webviews/settings/settingsWebview.ts +++ b/src/webviews/settings/settingsWebview.ts @@ -19,6 +19,7 @@ export class SettingsWebview extends WebviewWithConfigBase { 'settings.html', 'images/gitlens-icon.png', 'GitLens Settings', + 'settingsWebview', Commands.ShowSettingsPage, ); diff --git a/src/webviews/webviewBase.ts b/src/webviews/webviewBase.ts index 9a33c14..1eba674 100644 --- a/src/webviews/webviewBase.ts +++ b/src/webviews/webviewBase.ts @@ -5,6 +5,7 @@ import type { Commands } from '../constants'; import type { Container } from '../container'; import { Logger } from '../logger'; import { executeCommand, registerCommand } from '../system/command'; +import type { TrackedUsageFeatures } from '../usageTracker'; import type { IpcMessage, IpcMessageParams, IpcNotificationType } from './protocol'; import { ExecuteCommandType, onIpc, WebviewReadyCommandType } from './protocol'; @@ -33,6 +34,7 @@ export abstract class WebviewBase implements Disposable { private readonly fileName: string, private readonly iconPath: string, title: string, + private readonly trackingFeature: TrackedUsageFeatures, showCommand: Commands, ) { this._originalTitle = this._title = title; @@ -69,6 +71,8 @@ export abstract class WebviewBase implements Disposable { } async show(column: ViewColumn = ViewColumn.Beside, ..._args: any[]): Promise { + void this.container.usage.track(`${this.trackingFeature}:shown`); + // Only try to open beside if there is an active tab if (column === ViewColumn.Beside && window.tabGroups.activeTabGroup.activeTab == null) { column = ViewColumn.Active; diff --git a/src/webviews/webviewViewBase.ts b/src/webviews/webviewViewBase.ts index 6553b47..e2b8e6c 100644 --- a/src/webviews/webviewViewBase.ts +++ b/src/webviews/webviewViewBase.ts @@ -13,6 +13,7 @@ import type { Container } from '../container'; import { Logger } from '../logger'; import { executeCommand } from '../system/command'; import { getLogScope, log } from '../system/decorators/log'; +import type { TrackedUsageFeatures } from '../usageTracker'; import type { IpcMessage, IpcMessageParams, IpcNotificationType } from './protocol'; import { ExecuteCommandType, onIpc, WebviewReadyCommandType } from './protocol'; @@ -40,6 +41,7 @@ export abstract class WebviewViewBase implements public readonly id: `gitlens.views.${string}`, protected readonly fileName: string, title: string, + private readonly trackingFeature: TrackedUsageFeatures, ) { this._title = title; this.disposables.push(window.registerWebviewViewProvider(id, this)); @@ -142,6 +144,7 @@ export abstract class WebviewViewBase implements Logger.debug(`WebviewView(${this.id}).onViewVisibilityChanged`, `visible=${visible}`); if (visible) { + void this.container.usage.track(`${this.trackingFeature}:shown`); await this.refresh(); } this.onVisibilityChanged?.(visible); diff --git a/src/webviews/webviewWithConfigBase.ts b/src/webviews/webviewWithConfigBase.ts index fd49adb..8a68747 100644 --- a/src/webviews/webviewWithConfigBase.ts +++ b/src/webviews/webviewWithConfigBase.ts @@ -8,6 +8,7 @@ import { GitCommit, GitCommitIdentity } from '../git/models/commit'; import { GitFileChange, GitFileIndexStatus } from '../git/models/file'; import { PullRequest, PullRequestState } from '../git/models/pullRequest'; import { Logger } from '../logger'; +import type { TrackedUsageFeatures } from '../usageTracker'; import type { IpcMessage } from './protocol'; import { DidChangeConfigurationNotificationType, @@ -25,9 +26,10 @@ export abstract class WebviewWithConfigBase extends WebviewBase { fileName: string, iconPath: string, title: string, + trackingFeature: TrackedUsageFeatures, showCommand: Commands, ) { - super(container, id, fileName, iconPath, title, showCommand); + super(container, id, fileName, iconPath, title, trackingFeature, showCommand); this.disposables.push( configuration.onDidChange(this.onConfigurationChanged, this), configuration.onDidChangeAny(this.onAnyConfigurationChanged, this), diff --git a/src/webviews/welcome/welcomeWebview.ts b/src/webviews/welcome/welcomeWebview.ts index ae98c74..4a228c0 100644 --- a/src/webviews/welcome/welcomeWebview.ts +++ b/src/webviews/welcome/welcomeWebview.ts @@ -12,6 +12,7 @@ export class WelcomeWebview extends WebviewWithConfigBase { 'welcome.html', 'images/gitlens-icon.png', 'Welcome to GitLens', + 'welcomeWebview', Commands.ShowWelcomePage, ); }