chat - restore a checkbox but disabled for now (#235336)

pull/235349/head
Benjamin Pasero 2024-12-04 22:40:45 +01:00 committed by GitHub
parent 256bf5ec0a
commit 4a23ffeeff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 67 additions and 18 deletions

View File

@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.96.0",
"distro": "259941ab128814d2a40a076eecd74b25d4a37a5b",
"distro": "c883c91dadf5f063b26c86ffe01851acee3747c6",
"author": {
"name": "Microsoft Corporation"
},

View File

@ -310,8 +310,10 @@ export interface IDefaultChatAgent {
readonly termsStatementUrl: string;
readonly privacyStatementUrl: string;
readonly skusDocumentationUrl: string;
readonly publicCodeMatchesUrl: string;
readonly manageSettingsUrl: string;
readonly managePlanUrl: string;
readonly upgradePlanUrl: string;
readonly providerId: string;
readonly providerName: string;
readonly providerScopes: string[][];

View File

@ -133,7 +133,7 @@ export class ChatQuotasService extends Disposable implements IChatQuotasService
buttons: [
{
label: localize('managePlan', "Upgrade to Copilot Pro"),
run: () => { openerService.open(URI.parse(product.defaultChatAgent?.managePlanUrl ?? '')); }
run: () => { openerService.open(URI.parse(product.defaultChatAgent?.upgradePlanUrl ?? '')); }
},
],
custom: {

View File

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import './media/chatViewSetup.css';
import { $, getActiveElement, setVisibility } from '../../../../base/browser/dom.js';
import { $, addDisposableListener, EventType, getActiveElement, setVisibility } from '../../../../base/browser/dom.js';
import { Button, ButtonWithDropdown } from '../../../../base/browser/ui/button/button.js';
import { renderIcon } from '../../../../base/browser/ui/iconLabel/iconLabels.js';
import { IAction, toAction } from '../../../../base/common/actions.js';
@ -37,7 +37,7 @@ import { Registry } from '../../../../platform/registry/common/platform.js';
import { asText, IRequestService } from '../../../../platform/request/common/request.js';
import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js';
import { defaultButtonStyles } from '../../../../platform/theme/browser/defaultStyles.js';
import { defaultButtonStyles, defaultCheckboxStyles } from '../../../../platform/theme/browser/defaultStyles.js';
import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js';
import { IWorkbenchContribution } from '../../../common/contributions.js';
import { IViewDescriptorService, ViewContainerLocation } from '../../../common/views.js';
@ -55,6 +55,7 @@ import { ChatViewId, EditsViewId, ensureSideBarChatViewSize, IChatWidget, showCh
import { CHAT_EDITING_SIDEBAR_PANEL_ID, CHAT_SIDEBAR_PANEL_ID } from './chatViewPane.js';
import { ChatViewsWelcomeExtensions, IChatViewsWelcomeContributionRegistry } from './viewsWelcome/chatViewsWelcome.js';
import { IChatQuotasService } from './chatQuotasService.js';
import { Checkbox } from '../../../../base/browser/ui/toggle/toggle.js';
const defaultChat = {
extensionId: product.defaultChatAgent?.extensionId ?? '',
@ -63,12 +64,12 @@ const defaultChat = {
termsStatementUrl: product.defaultChatAgent?.termsStatementUrl ?? '',
privacyStatementUrl: product.defaultChatAgent?.privacyStatementUrl ?? '',
skusDocumentationUrl: product.defaultChatAgent?.skusDocumentationUrl ?? '',
publicCodeMatchesUrl: product.defaultChatAgent?.publicCodeMatchesUrl ?? '',
providerId: product.defaultChatAgent?.providerId ?? '',
providerName: product.defaultChatAgent?.providerName ?? '',
providerScopes: product.defaultChatAgent?.providerScopes ?? [[]],
entitlementUrl: product.defaultChatAgent?.entitlementUrl ?? '',
entitlementSignupLimitedUrl: product.defaultChatAgent?.entitlementSignupLimitedUrl ?? '',
managePlanUrl: product.defaultChatAgent?.managePlanUrl ?? '',
};
enum ChatEntitlement {
@ -86,6 +87,8 @@ enum ChatEntitlement {
Pro
}
const ASK_FOR_PUBLIC_CODE_MATCHES = false; // TODO@bpasero revisit this
//#region Contribution
const TRIGGER_SETUP_COMMAND_ID = 'workbench.action.chat.triggerSetup';
@ -179,7 +182,7 @@ export class ChatSetupContribution extends Disposable implements IWorkbenchContr
// Setup should be kicked off immediately
if (typeof startSetup === 'boolean' && startSetup) {
const controller = that.controller.value;
controller.setup();
controller.setup({ publicCodeSuggestions: true }); // TODO@sbatten pass in as argument
}
configurationService.updateValue('chat.commandCenter.enabled', true);
@ -506,10 +509,10 @@ class ChatSetupRequests extends Disposable {
return this.resolveEntitlement(session, CancellationToken.None);
}
async signUpLimited(session: AuthenticationSession): Promise<boolean> {
async signUpLimited(session: AuthenticationSession, options: { publicCodeSuggestions: boolean }): Promise<boolean> {
const body = {
restricted_telemetry: 'disabled',
public_code_suggestions: 'enabled'
public_code_suggestions: options.publicCodeSuggestions ? 'enabled' : 'disabled'
};
const response = await this.request(defaultChat.entitlementSignupLimitedUrl, 'POST', body, session, CancellationToken.None);
@ -621,7 +624,7 @@ class ChatSetupController extends Disposable {
this._onDidChange.fire();
}
async setup(): Promise<void> {
async setup(options: { publicCodeSuggestions: boolean }): Promise<void> {
const title = localize('setupChatProgress', "Getting Copilot ready...");
const badge = this.activityService.showViewContainerActivity(isCopilotEditsViewActive(this.viewsService) ? CHAT_EDITING_SIDEBAR_PANEL_ID : CHAT_SIDEBAR_PANEL_ID, {
badge: new ProgressBadge(() => title),
@ -633,13 +636,13 @@ class ChatSetupController extends Disposable {
location: ProgressLocation.Window,
command: TRIGGER_SETUP_COMMAND_ID,
title,
}, () => this.doSetup());
}, () => this.doSetup(options));
} finally {
badge.dispose();
}
}
private async doSetup(): Promise<void> {
private async doSetup(options: { publicCodeSuggestions: boolean }): Promise<void> {
this.context.suspend(); // reduces flicker
try {
let session: AuthenticationSession | undefined;
@ -666,7 +669,7 @@ class ChatSetupController extends Disposable {
// Install
this.setStep(ChatSetupStep.Installing);
await this.install(session, entitlement ?? this.context.state.entitlement);
await this.install(session, entitlement ?? this.context.state.entitlement, options);
} finally {
this.setStep(ChatSetupStep.Initial);
this.context.resume();
@ -691,7 +694,7 @@ class ChatSetupController extends Disposable {
return { session, entitlement };
}
private async install(session: AuthenticationSession, entitlement: ChatEntitlement): Promise<void> {
private async install(session: AuthenticationSession, entitlement: ChatEntitlement, options: { publicCodeSuggestions: boolean }): Promise<void> {
const signedIn = !!session;
const activeElement = getActiveElement();
@ -702,7 +705,7 @@ class ChatSetupController extends Disposable {
showCopilotView(this.viewsService);
if (entitlement !== ChatEntitlement.Limited && entitlement !== ChatEntitlement.Pro && entitlement !== ChatEntitlement.Unavailable) {
didSignUp = await this.requests.signUpLimited(session);
didSignUp = await this.requests.signUpLimited(session, options);
}
await this.extensionsWorkbenchService.install(defaultChat.extensionId, {
@ -789,6 +792,9 @@ class ChatSetupWelcomeContent extends Disposable {
const limitedSkuHeaderContainer = this.element.appendChild($('p'));
limitedSkuHeaderContainer.appendChild(this._register(markdown.render(new MarkdownString(limitedSkuHeader, { isTrusted: true, supportThemeIcons: true }))).element);
const publicCodeSuggestionsLabel = localize('detectionLabel', "Allow code suggestions that [match public code]({0})", defaultChat.publicCodeMatchesUrl);
const { container: publicCodeSuggestionsContainer, checkbox: publicCodeSuggestionsCheckbox } = this.createCheckBox(publicCodeSuggestionsLabel, true, markdown);
// Terms
const terms = localize({ key: 'termsLabel', comment: ['{Locked="["}', '{Locked="]({0})"}', '{Locked="]({1})"}'] }, "By continuing, you agree to our [Terms]({0}) and [Privacy Policy]({1}).", defaultChat.termsStatementUrl, defaultChat.privacyStatementUrl);
this.element.appendChild($('p')).appendChild(this._register(markdown.render(new MarkdownString(terms, { isTrusted: true }))).element);
@ -810,13 +816,30 @@ class ChatSetupWelcomeContent extends Disposable {
supportIcons: true,
...defaultButtonStyles
}));
this._register(button.onDidClick(() => this.controller.setup()));
this._register(button.onDidClick(() => this.controller.setup({ publicCodeSuggestions: ASK_FOR_PUBLIC_CODE_MATCHES ? publicCodeSuggestionsCheckbox.checked : true })));
// Update based on model state
this._register(Event.runAndSubscribe(this.controller.onDidChange, () => this.update(limitedSkuHeaderContainer, button)));
this._register(Event.runAndSubscribe(this.controller.onDidChange, () => this.update(limitedSkuHeaderContainer, button, [publicCodeSuggestionsContainer], [publicCodeSuggestionsCheckbox])));
}
private update(limitedSkuHeaderContainer: HTMLElement, button: Button | ButtonWithDropdown): void {
private createCheckBox(label: string, checked: boolean, markdown: MarkdownRenderer): { container: HTMLElement; checkbox: Checkbox } {
const container = this.element.appendChild($('p.checkbox-container'));
const checkbox = this._register(new Checkbox(label, checked, defaultCheckboxStyles));
container.appendChild(checkbox.domNode);
const checkboxLabel = container.appendChild(this._register(markdown.render(new MarkdownString(label, { isTrusted: true, supportThemeIcons: true }), { inline: true, className: 'checkbox-label' })).element);
this._register(addDisposableListener(checkboxLabel, EventType.CLICK, e => {
if (checkbox?.enabled && (e.target as HTMLElement).tagName !== 'A') {
checkbox.checked = !checkbox.checked;
checkbox.focus();
}
}));
return { container, checkbox };
}
private update(limitedSkuHeaderContainer: HTMLElement, button: Button | ButtonWithDropdown, limitedCheckboxContainers: HTMLElement[], limitedCheckboxes: Checkbox[]): void {
const showLimitedCheckboxes = ASK_FOR_PUBLIC_CODE_MATCHES ? this.context.state.entitlement !== ChatEntitlement.Limited && this.context.state.entitlement !== ChatEntitlement.Pro && this.context.state.entitlement !== ChatEntitlement.Unavailable : false;
let showLimitedSkuHeader: boolean;
let buttonLabel: string;
@ -840,17 +863,26 @@ class ChatSetupWelcomeContent extends Disposable {
switch (this.controller.step) {
case ChatSetupStep.Initial:
// do not override
for (const checkbox of limitedCheckboxes) {
checkbox.enable();
}
break;
case ChatSetupStep.SigningIn:
for (const checkbox of limitedCheckboxes) {
checkbox.disable();
}
buttonLabel = localize('setupChatSignIn', "$(loading~spin) Signing in to {0}...", defaultChat.providerName);
break;
case ChatSetupStep.Installing:
for (const checkbox of limitedCheckboxes) {
checkbox.disable();
}
buttonLabel = localize('setupChatInstalling', "$(loading~spin) Getting Copilot Ready...");
break;
}
setVisibility(showLimitedSkuHeader, limitedSkuHeaderContainer);
setVisibility(showLimitedCheckboxes, ...limitedCheckboxContainers);
button.label = buttonLabel;
button.enabled = this.controller.step === ChatSetupStep.Initial;

View File

@ -50,4 +50,19 @@
width: 100%;
padding: 4px 7px;
}
/** Checkboxes */
.checkbox-container {
display: flex;
padding-top: 20px;
}
.checkbox-label {
flex-basis: fit-content;
cursor: pointer;
}
.checkbox-label p {
display: inline;
}
}