Path: blob/main/src/vs/workbench/contrib/editTelemetry/browser/editStats/aiStatsStatusBar.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { n } from '../../../../../base/browser/dom.js';6import { ActionBar, IActionBarOptions, IActionOptions } from '../../../../../base/browser/ui/actionbar/actionbar.js';7import { IAction } from '../../../../../base/common/actions.js';8import { Codicon } from '../../../../../base/common/codicons.js';9import { createHotClass } from '../../../../../base/common/hotReloadHelpers.js';10import { Disposable, DisposableStore } from '../../../../../base/common/lifecycle.js';11import { autorun, derived } from '../../../../../base/common/observable.js';12import { ThemeIcon } from '../../../../../base/common/themables.js';13import { localize } from '../../../../../nls.js';14import { ICommandService } from '../../../../../platform/commands/common/commands.js';15import { nativeHoverDelegate } from '../../../../../platform/hover/browser/hover.js';16import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js';17import { IStatusbarService, StatusbarAlignment } from '../../../../services/statusbar/browser/statusbar.js';18import { AI_STATS_SETTING_ID } from '../settingIds.js';19import type { AiStatsFeature } from './aiStatsFeature.js';20import './media.css';2122export class AiStatsStatusBar extends Disposable {23public static readonly hot = createHotClass(AiStatsStatusBar);2425constructor(26private readonly _aiStatsFeature: AiStatsFeature,27@IStatusbarService private readonly _statusbarService: IStatusbarService,28@ICommandService private readonly _commandService: ICommandService,29@ITelemetryService private readonly _telemetryService: ITelemetryService,30) {31super();3233this._register(autorun((reader) => {34const statusBarItem = this._createStatusBar().keepUpdated(reader.store);3536const store = this._register(new DisposableStore());3738reader.store.add(this._statusbarService.addEntry({39name: localize('inlineSuggestions', "Inline Suggestions"),40ariaLabel: localize('inlineSuggestionsStatusBar', "Inline suggestions status bar"),41text: '',42tooltip: {43element: async (_token) => {44this._sendHoverTelemetry();45store.clear();46const elem = this._createStatusBarHover();47return elem.keepUpdated(store).element;48},49markdownNotSupportedFallback: undefined,50},51content: statusBarItem.element,52}, 'aiStatsStatusBar', StatusbarAlignment.RIGHT, 100));53}));54}5556private _sendHoverTelemetry(): void {57this._telemetryService.publicLog2<{58aiRate: number;59}, {60owner: 'hediet';61comment: 'Fired when the AI stats status bar hover tooltip is shown';62aiRate: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The current AI rate percentage' };63}>(64'aiStatsStatusBar.hover',65{66aiRate: this._aiStatsFeature.aiRate.get(),67}68);69}707172private _createStatusBar() {73return n.div({74style: {75height: '100%',76display: 'flex',77alignItems: 'center',78justifyContent: 'center',79}80}, [81n.div(82{83class: 'ai-stats-status-bar',84style: {85display: 'flex',86flexDirection: 'column',8788width: 50,89height: 6,9091borderRadius: 6,92borderWidth: '1px',93borderStyle: 'solid',94}95},96[97n.div({98style: {99flex: 1,100101display: 'flex',102overflow: 'hidden',103104borderRadius: 6,105border: '1px solid transparent',106}107}, [108n.div({109style: {110width: this._aiStatsFeature.aiRate.map(v => `${v * 100}%`),111backgroundColor: 'currentColor',112}113})114])115]116)117]);118}119120private _createStatusBarHover() {121const aiRatePercent = this._aiStatsFeature.aiRate.map(r => `${Math.round(r * 100)}%`);122123return n.div({124class: 'ai-stats-status-bar',125}, [126n.div({127class: 'header',128style: {129minWidth: '200px',130}131},132[133n.div({ style: { flex: 1 } }, [localize('aiStatsStatusBarHeader', "AI Usage Statistics")]),134n.div({ style: { marginLeft: 'auto' } }, actionBar([135{136action: {137id: 'aiStats.statusBar.settings',138label: '',139enabled: true,140run: () => openSettingsCommand({ ids: [AI_STATS_SETTING_ID] }).run(this._commandService),141class: ThemeIcon.asClassName(Codicon.gear),142tooltip: localize('aiStats.statusBar.configure', "Configure")143},144options: { icon: true, label: false, hoverDelegate: nativeHoverDelegate }145}146]))147]148),149150n.div({ style: { display: 'flex' } }, [151n.div({ style: { flex: 1, paddingRight: '4px' } }, [152localize('text1', "AI vs Typing Average: {0}", aiRatePercent.get()),153]),154/*155TODO: Write article that explains the ratio and link to it.156157n.div({ style: { marginLeft: 'auto' } }, actionBar([158{159action: {160id: 'aiStatsStatusBar.openSettings',161label: '',162enabled: true,163run: () => { },164class: ThemeIcon.asClassName(Codicon.info),165tooltip: ''166},167options: { icon: true, label: true, }168}169]))*/170]),171n.div({ style: { flex: 1, paddingRight: '4px' } }, [172localize('text2', "Accepted inline suggestions today: {0}", this._aiStatsFeature.acceptedInlineSuggestionsToday.get()),173]),174]);175}176}177178function actionBar(actions: { action: IAction; options: IActionOptions }[], options?: IActionBarOptions) {179return derived((_reader) => n.div({180class: [],181style: {182},183ref: elem => {184const actionBar = _reader.store.add(new ActionBar(elem, options));185for (const { action, options } of actions) {186actionBar.push(action, options);187}188}189}));190}191192class CommandWithArgs {193constructor(194public readonly commandId: string,195public readonly args: unknown[] = [],196) { }197198public run(commandService: ICommandService): void {199commandService.executeCommand(this.commandId, ...this.args);200}201}202203function openSettingsCommand(options: { ids?: string[] } = {}) {204return new CommandWithArgs('workbench.action.openSettings', [{205query: options.ids ? options.ids.map(id => `@id:${id}`).join(' ') : undefined,206}]);207}208209210