Skip to content

Commit 092b63b

Browse files
authored
chat - add explicit action to force sign in dialog (microsoft#255965)
This will be used from the chat extension as last resort if chat is not functional.
1 parent dd8f681 commit 092b63b

File tree

1 file changed

+34
-14
lines changed

1 file changed

+34
-14
lines changed

src/vs/workbench/contrib/chat/browser/chatSetup.ts

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ class ChatSetup {
616616
this.skipDialogOnce = true;
617617
}
618618

619-
async run(options?: { disableChatViewReveal?: boolean }): Promise<IChatSetupResult> {
619+
async run(options?: { disableChatViewReveal?: boolean; forceSignInDialog?: boolean }): Promise<IChatSetupResult> {
620620
if (this.pendingRun) {
621621
return this.pendingRun;
622622
}
@@ -630,7 +630,7 @@ class ChatSetup {
630630
}
631631
}
632632

633-
private async doRun(options?: { disableChatViewReveal?: boolean }): Promise<IChatSetupResult> {
633+
private async doRun(options?: { disableChatViewReveal?: boolean; forceSignInDialog?: boolean }): Promise<IChatSetupResult> {
634634
this.context.update({ later: false });
635635

636636
const dialogSkipped = this.skipDialogOnce;
@@ -647,10 +647,10 @@ class ChatSetup {
647647
}
648648

649649
let setupStrategy: ChatSetupStrategy;
650-
if (dialogSkipped || isProUser(this.chatEntitlementService.entitlement) || this.chatEntitlementService.entitlement === ChatEntitlement.Free) {
650+
if (!options?.forceSignInDialog && (dialogSkipped || isProUser(this.chatEntitlementService.entitlement) || this.chatEntitlementService.entitlement === ChatEntitlement.Free)) {
651651
setupStrategy = ChatSetupStrategy.DefaultSetup; // existing pro/free users setup without a dialog
652652
} else {
653-
setupStrategy = await this.showDialog();
653+
setupStrategy = await this.showDialog(options);
654654
}
655655

656656
if (setupStrategy === ChatSetupStrategy.DefaultSetup && ChatEntitlementRequests.providerId(this.configurationService) === defaultChat.provider.enterprise.id) {
@@ -694,15 +694,15 @@ class ChatSetup {
694694
return { success, dialogSkipped };
695695
}
696696

697-
private async showDialog(): Promise<ChatSetupStrategy> {
697+
private async showDialog(options?: { forceSignInDialog?: boolean }): Promise<ChatSetupStrategy> {
698698
const disposables = new DisposableStore();
699699

700700
const dialogVariant = this.configurationService.getValue<'default' | 'apple' | unknown>('chat.setup.signInDialogVariant');
701-
const buttons = this.getButtons(dialogVariant);
701+
const buttons = this.getButtons(dialogVariant, options);
702702

703703
const dialog = disposables.add(new Dialog(
704704
this.layoutService.activeContainer,
705-
this.getDialogTitle(),
705+
this.getDialogTitle(options),
706706
buttons.map(button => button[0]),
707707
createWorkbenchDialogOptions({
708708
type: 'none',
@@ -723,12 +723,12 @@ class ChatSetup {
723723
return buttons[button]?.[1] ?? ChatSetupStrategy.Canceled;
724724
}
725725

726-
private getButtons(variant: 'default' | 'apple' | unknown): Array<[string, ChatSetupStrategy, { styleButton?: (button: IButton) => void } | undefined]> {
726+
private getButtons(variant: 'default' | 'apple' | unknown, options?: { forceSignInDialog?: boolean }): Array<[string, ChatSetupStrategy, { styleButton?: (button: IButton) => void } | undefined]> {
727727
type ContinueWithButton = [string, ChatSetupStrategy, { styleButton?: (button: IButton) => void } | undefined];
728728
const styleButton = (...classes: string[]) => ({ styleButton: (button: IButton) => button.element.classList.add(...classes) });
729729

730730
let buttons: Array<ContinueWithButton>;
731-
if (this.context.state.entitlement === ChatEntitlement.Unknown) {
731+
if (this.context.state.entitlement === ChatEntitlement.Unknown || options?.forceSignInDialog) {
732732
const defaultProviderButton: ContinueWithButton = [localize('continueWith', "Continue with {0}", defaultChat.provider.default.name), ChatSetupStrategy.SetupWithoutEnterpriseProvider, styleButton('continue-button', 'default')];
733733
const defaultProviderLink: ContinueWithButton = [defaultProviderButton[0], defaultProviderButton[1], styleButton('link-button')];
734734

@@ -762,8 +762,8 @@ class ChatSetup {
762762
return buttons;
763763
}
764764

765-
private getDialogTitle(): string {
766-
if (this.context.state.entitlement === ChatEntitlement.Unknown) {
765+
private getDialogTitle(options?: { forceSignInDialog?: boolean }): string {
766+
if (this.context.state.entitlement === ChatEntitlement.Unknown || options?.forceSignInDialog) {
767767
return localize('signIn', "Sign in to use Copilot");
768768
}
769769

@@ -882,7 +882,7 @@ export class ChatSetupContribution extends Disposable implements IWorkbenchContr
882882
});
883883
}
884884

885-
override async run(accessor: ServicesAccessor, mode: ChatModeKind): Promise<boolean> {
885+
override async run(accessor: ServicesAccessor, mode?: ChatModeKind, options?: { forceSignInDialog?: boolean }): Promise<boolean> {
886886
const viewsService = accessor.get(IViewsService);
887887
const layoutService = accessor.get(IWorkbenchLayoutService);
888888
const instantiationService = accessor.get(IInstantiationService);
@@ -898,7 +898,7 @@ export class ChatSetupContribution extends Disposable implements IWorkbenchContr
898898
}
899899

900900
const setup = ChatSetup.getInstance(instantiationService, context, controller);
901-
const { success } = await setup.run();
901+
const { success } = await setup.run(options);
902902
if (success === false && !lifecycleService.willShutdown) {
903903
const { confirmed } = await dialogService.confirm({
904904
type: Severity.Error,
@@ -907,14 +907,33 @@ export class ChatSetupContribution extends Disposable implements IWorkbenchContr
907907
});
908908

909909
if (confirmed) {
910-
return Boolean(await commandService.executeCommand(CHAT_SETUP_ACTION_ID, mode));
910+
return Boolean(await commandService.executeCommand(CHAT_SETUP_ACTION_ID, mode, options));
911911
}
912912
}
913913

914914
return Boolean(success);
915915
}
916916
}
917917

918+
class ChatSetupTriggerForceSignInDialogAction extends Action2 {
919+
920+
constructor() {
921+
super({
922+
id: 'workbench.action.chat.triggerSetupForceSignIn',
923+
title: localize2('forceSignIn', "Sign in to use Copilot")
924+
});
925+
}
926+
927+
override async run(accessor: ServicesAccessor): Promise<void> {
928+
const commandService = accessor.get(ICommandService);
929+
const telemetryService = accessor.get(ITelemetryService);
930+
931+
telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', { id: CHAT_SETUP_ACTION_ID, from: 'api' });
932+
933+
return commandService.executeCommand(CHAT_SETUP_ACTION_ID, undefined, { forceSignInDialog: true });
934+
}
935+
}
936+
918937
class ChatSetupTriggerWithoutDialogAction extends Action2 {
919938

920939
constructor() {
@@ -1105,6 +1124,7 @@ export class ChatSetupContribution extends Disposable implements IWorkbenchContr
11051124
}
11061125

11071126
registerAction2(ChatSetupTriggerAction);
1127+
registerAction2(ChatSetupTriggerForceSignInDialogAction);
11081128
registerAction2(ChatSetupFromAccountsAction);
11091129
registerAction2(ChatSetupTriggerWithoutDialogAction);
11101130
registerAction2(ChatSetupHideAction);

0 commit comments

Comments
 (0)