Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/api/browser/mainThreadMessageService.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as nls from '../../../nls.js';
7
import Severity from '../../../base/common/severity.js';
8
import { IAction, toAction } from '../../../base/common/actions.js';
9
import { MainThreadMessageServiceShape, MainContext, MainThreadMessageOptions } from '../common/extHost.protocol.js';
10
import { extHostNamedCustomer, IExtHostContext } from '../../services/extensions/common/extHostCustomers.js';
11
import { IDialogService, IPromptButton } from '../../../platform/dialogs/common/dialogs.js';
12
import { INotificationService, INotificationSource, NotificationPriority } from '../../../platform/notification/common/notification.js';
13
import { Event } from '../../../base/common/event.js';
14
import { ICommandService } from '../../../platform/commands/common/commands.js';
15
import { IExtensionService } from '../../services/extensions/common/extensions.js';
16
import { IDisposable } from '../../../base/common/lifecycle.js';
17
18
@extHostNamedCustomer(MainContext.MainThreadMessageService)
19
export class MainThreadMessageService implements MainThreadMessageServiceShape {
20
21
private extensionsListener: IDisposable;
22
23
private static readonly URGENT_NOTIFICATION_SOURCES = [
24
'vscode.github-authentication',
25
'vscode.microsoft-authentication'
26
];
27
28
constructor(
29
extHostContext: IExtHostContext,
30
@INotificationService private readonly _notificationService: INotificationService,
31
@ICommandService private readonly _commandService: ICommandService,
32
@IDialogService private readonly _dialogService: IDialogService,
33
@IExtensionService extensionService: IExtensionService
34
) {
35
this.extensionsListener = extensionService.onDidChangeExtensions(e => {
36
for (const extension of e.removed) {
37
this._notificationService.removeFilter(extension.identifier.value);
38
}
39
});
40
}
41
42
dispose(): void {
43
this.extensionsListener.dispose();
44
}
45
46
$showMessage(severity: Severity, message: string, options: MainThreadMessageOptions, commands: { title: string; isCloseAffordance: boolean; handle: number }[]): Promise<number | undefined> {
47
if (options.modal) {
48
return this._showModalMessage(severity, message, options.detail, commands, options.useCustom);
49
} else {
50
return this._showMessage(severity, message, commands, options);
51
}
52
}
53
54
private _showMessage(severity: Severity, message: string, commands: { title: string; isCloseAffordance: boolean; handle: number }[], options: MainThreadMessageOptions): Promise<number | undefined> {
55
56
return new Promise<number | undefined>(resolve => {
57
58
const primaryActions: IAction[] = commands.map(command => toAction({
59
id: `_extension_message_handle_${command.handle}`,
60
label: command.title,
61
enabled: true,
62
run: () => {
63
resolve(command.handle);
64
return Promise.resolve();
65
}
66
}));
67
68
let source: string | INotificationSource | undefined;
69
let sourceIsUrgent = false;
70
if (options.source) {
71
source = {
72
label: options.source.label,
73
id: options.source.identifier.value
74
};
75
sourceIsUrgent = MainThreadMessageService.URGENT_NOTIFICATION_SOURCES.includes(source.id);
76
}
77
78
if (!source) {
79
source = nls.localize('defaultSource', "Extension");
80
}
81
82
const secondaryActions: IAction[] = [];
83
if (options.source) {
84
secondaryActions.push(toAction({
85
id: options.source.identifier.value,
86
label: nls.localize('manageExtension', "Manage Extension"),
87
run: () => {
88
return this._commandService.executeCommand('_extensions.manage', options.source!.identifier.value);
89
}
90
}));
91
}
92
93
const messageHandle = this._notificationService.notify({
94
severity,
95
message,
96
actions: { primary: primaryActions, secondary: secondaryActions },
97
source,
98
priority: sourceIsUrgent ? NotificationPriority.URGENT : NotificationPriority.DEFAULT,
99
sticky: sourceIsUrgent
100
});
101
102
// if promise has not been resolved yet, now is the time to ensure a return value
103
// otherwise if already resolved it means the user clicked one of the buttons
104
Event.once(messageHandle.onDidClose)(() => {
105
resolve(undefined);
106
});
107
});
108
}
109
110
private async _showModalMessage(severity: Severity, message: string, detail: string | undefined, commands: { title: string; isCloseAffordance: boolean; handle: number }[], useCustom?: boolean): Promise<number | undefined> {
111
const buttons: IPromptButton<number>[] = [];
112
let cancelButton: IPromptButton<number | undefined> | undefined = undefined;
113
114
for (const command of commands) {
115
const button: IPromptButton<number> = {
116
label: command.title,
117
run: () => command.handle
118
};
119
120
if (command.isCloseAffordance) {
121
cancelButton = button;
122
} else {
123
buttons.push(button);
124
}
125
}
126
127
if (!cancelButton) {
128
if (buttons.length > 0) {
129
cancelButton = {
130
label: nls.localize('cancel', "Cancel"),
131
run: () => undefined
132
};
133
} else {
134
cancelButton = {
135
label: nls.localize({ key: 'ok', comment: ['&& denotes a mnemonic'] }, "&&OK"),
136
run: () => undefined
137
};
138
}
139
}
140
141
const { result } = await this._dialogService.prompt({
142
type: severity,
143
message,
144
detail,
145
buttons,
146
cancelButton,
147
custom: useCustom
148
});
149
150
return result;
151
}
152
}
153
154