mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-27 20:13:32 +01:00
notifications - add service methods to DND per source
This commit is contained in:
committed by
Benjamin Pasero
parent
968af29545
commit
0ff10eb8f3
@@ -42,7 +42,7 @@ import { IKeybindingItem, KeybindingsRegistry } from 'vs/platform/keybinding/com
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
import { ILabelService, ResourceLabelFormatter, IFormatterChangeEvent, Verbosity } from 'vs/platform/label/common/label';
|
||||
import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions } from 'vs/platform/notification/common/notification';
|
||||
import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions, INotificationSource } from 'vs/platform/notification/common/notification';
|
||||
import { IProgressRunner, IEditorProgressService, IProgressService, IProgress, IProgressCompositeOptions, IProgressDialogOptions, IProgressNotificationOptions, IProgressOptions, IProgressStep, IProgressWindowOptions } from 'vs/platform/progress/common/progress';
|
||||
import { ITelemetryService, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier, IWorkspace, IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, IWorkspaceFoldersWillChangeEvent, WorkbenchState, WorkspaceFolder, STANDALONE_EDITOR_WORKSPACE_ID } from 'vs/platform/workspace/common/workspace';
|
||||
@@ -306,11 +306,13 @@ export class StandaloneNotificationService implements INotificationService {
|
||||
|
||||
readonly onDidRemoveNotification: Event<INotification> = Event.None;
|
||||
|
||||
readonly onDidChangeDoNotDisturbMode: Event<void> = Event.None;
|
||||
readonly onDidChangeGlobalDoNotDisturbMode: Event<void> = Event.None;
|
||||
|
||||
readonly onDidChangePerSourceDoNotDisturbMode = Event.None;
|
||||
|
||||
public _serviceBrand: undefined;
|
||||
|
||||
public isDoNotDisturbMode: boolean = false;
|
||||
public isGlobalDoNotDisturbMode: boolean = false;
|
||||
|
||||
private static readonly NO_OP: INotificationHandle = new NoOpNotification();
|
||||
|
||||
@@ -350,9 +352,14 @@ export class StandaloneNotificationService implements INotificationService {
|
||||
return Disposable.None;
|
||||
}
|
||||
|
||||
public setDoNotDisturbMode(mode: boolean): void {
|
||||
this.isDoNotDisturbMode = mode;
|
||||
public setGlobalDoNotDisturbMode(mode: boolean): void {
|
||||
this.isGlobalDoNotDisturbMode = mode;
|
||||
}
|
||||
|
||||
public isSourceDoNotDisturb(source: INotificationSource): boolean {
|
||||
return false;
|
||||
}
|
||||
public setSourceDoNotDisturb(source: INotificationSource, mode: boolean): void { }
|
||||
}
|
||||
|
||||
export class StandaloneCommandService implements ICommandService {
|
||||
|
||||
@@ -17,7 +17,7 @@ import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKe
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
import { createUSLayoutResolvedKeybinding } from 'vs/platform/keybinding/test/common/keybindingsTestUtils';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { INotification, INotificationService, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification } from 'vs/platform/notification/common/notification';
|
||||
import { INotification, INotificationService, INotificationSource, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification } from 'vs/platform/notification/common/notification';
|
||||
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
|
||||
function createContext(ctx: any) {
|
||||
@@ -142,10 +142,11 @@ suite('AbstractKeybindingService', () => {
|
||||
|
||||
const notificationService: INotificationService = {
|
||||
_serviceBrand: undefined,
|
||||
isDoNotDisturbMode: false,
|
||||
isGlobalDoNotDisturbMode: false,
|
||||
onDidAddNotification: undefined!,
|
||||
onDidRemoveNotification: undefined!,
|
||||
onDidChangeDoNotDisturbMode: undefined!,
|
||||
onDidChangeGlobalDoNotDisturbMode: undefined!,
|
||||
onDidChangePerSourceDoNotDisturbMode: undefined!,
|
||||
notify: (notification: INotification) => {
|
||||
showMessageCalls.push({ sev: notification.severity, message: notification.message });
|
||||
return new NoOpNotification();
|
||||
@@ -173,8 +174,14 @@ suite('AbstractKeybindingService', () => {
|
||||
}
|
||||
};
|
||||
},
|
||||
setDoNotDisturbMode(mode: boolean) {
|
||||
setGlobalDoNotDisturbMode(mode: boolean) {
|
||||
throw new Error('not implemented');
|
||||
},
|
||||
isSourceDoNotDisturb(source: INotificationSource): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
},
|
||||
setSourceDoNotDisturb(source: INotificationSource, mode: boolean): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -97,6 +97,29 @@ export interface INeverShowAgainOptions {
|
||||
readonly scope?: NeverShowAgainScope;
|
||||
}
|
||||
|
||||
export interface INotificationSource {
|
||||
|
||||
/**
|
||||
* The id of the source.
|
||||
*/
|
||||
readonly id: string;
|
||||
|
||||
/**
|
||||
* The label of the source.
|
||||
*/
|
||||
readonly label: string;
|
||||
}
|
||||
|
||||
export function isNotificationSource(thing: unknown): thing is INotificationSource {
|
||||
if (thing) {
|
||||
const candidate = thing as INotificationSource;
|
||||
|
||||
return typeof candidate.id === 'string' && typeof candidate.label === 'string';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export interface INotification extends INotificationProperties {
|
||||
|
||||
/**
|
||||
@@ -120,7 +143,7 @@ export interface INotification extends INotificationProperties {
|
||||
/**
|
||||
* The source of the notification appears as additional information.
|
||||
*/
|
||||
readonly source?: string | { label: string; id: string };
|
||||
readonly source?: string | INotificationSource;
|
||||
|
||||
/**
|
||||
* Actions to show as part of the notification. Primary actions show up as
|
||||
@@ -343,19 +366,34 @@ export interface INotificationService {
|
||||
readonly onDidRemoveNotification: Event<INotification>;
|
||||
|
||||
/**
|
||||
* Emitted when a do not disturb mode has changed.
|
||||
* Emitted when the global do not disturb mode has changed.
|
||||
*/
|
||||
readonly onDidChangeDoNotDisturbMode: Event<void>;
|
||||
readonly onDidChangeGlobalDoNotDisturbMode: Event<void>;
|
||||
|
||||
/**
|
||||
* If enabled, only error messages will show as toasts.
|
||||
*/
|
||||
readonly isDoNotDisturbMode: boolean;
|
||||
readonly isGlobalDoNotDisturbMode: boolean;
|
||||
|
||||
/**
|
||||
* Enables or disables the do not disturb mode.
|
||||
* Enables or disables the global do not disturb mode.
|
||||
*/
|
||||
setDoNotDisturbMode(mode: boolean): void;
|
||||
setGlobalDoNotDisturbMode(mode: boolean): void;
|
||||
|
||||
/**
|
||||
* Emitted when the per-source do not disturb mode has changed.
|
||||
*/
|
||||
readonly onDidChangePerSourceDoNotDisturbMode: Event<INotificationSource>;
|
||||
|
||||
/**
|
||||
* Whether the provided source is configured as do not disturb.
|
||||
*/
|
||||
isSourceDoNotDisturb(source: INotificationSource): boolean;
|
||||
|
||||
/**
|
||||
* Enables or disables the per-source do not disturb mode.
|
||||
*/
|
||||
setSourceDoNotDisturb(source: INotificationSource, mode: boolean): void;
|
||||
|
||||
/**
|
||||
* Show the provided notification to the user. The returned `INotificationHandle`
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { INotification, INotificationHandle, INotificationService, INotificationSource, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification, Severity } from 'vs/platform/notification/common/notification';
|
||||
|
||||
export class TestNotificationService implements INotificationService {
|
||||
|
||||
@@ -13,11 +13,13 @@ export class TestNotificationService implements INotificationService {
|
||||
|
||||
readonly onDidRemoveNotification: Event<INotification> = Event.None;
|
||||
|
||||
readonly onDidChangeDoNotDisturbMode: Event<void> = Event.None;
|
||||
readonly onDidChangeGlobalDoNotDisturbMode: Event<void> = Event.None;
|
||||
|
||||
readonly onDidChangePerSourceDoNotDisturbMode = Event.None;
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
isDoNotDisturbMode: boolean = false;
|
||||
isGlobalDoNotDisturbMode: boolean = false;
|
||||
|
||||
private static readonly NO_OP: INotificationHandle = new NoOpNotification();
|
||||
|
||||
@@ -45,7 +47,13 @@ export class TestNotificationService implements INotificationService {
|
||||
return Disposable.None;
|
||||
}
|
||||
|
||||
setDoNotDisturbMode(mode: boolean): void {
|
||||
this.isDoNotDisturbMode = mode;
|
||||
setGlobalDoNotDisturbMode(mode: boolean): void {
|
||||
this.isGlobalDoNotDisturbMode = mode;
|
||||
}
|
||||
|
||||
isSourceDoNotDisturb(source: INotificationSource): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
setSourceDoNotDisturb(source: INotificationSource, mode: boolean): void { }
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { DeferredPromise } from 'vs/base/common/async';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { NotificationPriority } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationSource, NotificationPriority } from 'vs/platform/notification/common/notification';
|
||||
|
||||
export const IProgressService = createDecorator<IProgressService>('progressService');
|
||||
|
||||
@@ -53,7 +53,7 @@ export const enum ProgressLocation {
|
||||
export interface IProgressOptions {
|
||||
readonly location: ProgressLocation | string;
|
||||
readonly title?: string;
|
||||
readonly source?: string | { label: string; id: string };
|
||||
readonly source?: string | INotificationSource;
|
||||
readonly total?: number;
|
||||
readonly cancellable?: boolean;
|
||||
readonly buttons?: string[];
|
||||
|
||||
@@ -9,7 +9,7 @@ import { IAction, toAction } from 'vs/base/common/actions';
|
||||
import { MainThreadMessageServiceShape, MainContext, MainThreadMessageOptions } from '../common/extHost.protocol';
|
||||
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
|
||||
import { IDialogService, IPromptButton } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationService, INotificationSource } from 'vs/platform/notification/common/notification';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
|
||||
@@ -51,7 +51,7 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape {
|
||||
}
|
||||
}));
|
||||
|
||||
let source: string | { label: string; id: string } | undefined;
|
||||
let source: string | INotificationSource | undefined;
|
||||
if (options.source) {
|
||||
source = {
|
||||
label: nls.localize('extensionSource', "{0} (Extension)", options.source.label),
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as assert from 'assert';
|
||||
import { MainThreadMessageService } from 'vs/workbench/api/browser/mainThreadMessageService';
|
||||
import { IDialogService, IPrompt, IPromptButton } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice, IPromptOptions, IStatusMessageOptions } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice, IPromptOptions, IStatusMessageOptions, INotificationSource } from 'vs/platform/notification/common/notification';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { mock } from 'vs/base/test/common/mock';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
@@ -25,10 +25,11 @@ const emptyCommandService: ICommandService = {
|
||||
|
||||
const emptyNotificationService = new class implements INotificationService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
isDoNotDisturbMode: boolean = false;
|
||||
isGlobalDoNotDisturbMode: boolean = false;
|
||||
onDidAddNotification: Event<INotification> = Event.None;
|
||||
onDidRemoveNotification: Event<INotification> = Event.None;
|
||||
onDidChangeDoNotDisturbMode: Event<void> = Event.None;
|
||||
onDidChangeGlobalDoNotDisturbMode: Event<void> = Event.None;
|
||||
onDidChangePerSourceDoNotDisturbMode = Event.None;
|
||||
notify(...args: any[]): never {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
@@ -47,20 +48,27 @@ const emptyNotificationService = new class implements INotificationService {
|
||||
status(message: string | Error, options?: IStatusMessageOptions): IDisposable {
|
||||
return Disposable.None;
|
||||
}
|
||||
setDoNotDisturbMode(mode: boolean): void {
|
||||
setGlobalDoNotDisturbMode(mode: boolean): void {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
isSourceDoNotDisturb(source: INotificationSource): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
setSourceDoNotDisturb(source: INotificationSource, mode: boolean): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
};
|
||||
|
||||
class EmptyNotificationService implements INotificationService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
isDoNotDisturbMode: boolean = false;
|
||||
isGlobalDoNotDisturbMode: boolean = false;
|
||||
constructor(private withNotify: (notification: INotification) => void) {
|
||||
}
|
||||
|
||||
onDidAddNotification: Event<INotification> = Event.None;
|
||||
onDidRemoveNotification: Event<INotification> = Event.None;
|
||||
onDidChangeDoNotDisturbMode: Event<void> = Event.None;
|
||||
onDidChangeGlobalDoNotDisturbMode: Event<void> = Event.None;
|
||||
onDidChangePerSourceDoNotDisturbMode = Event.None;
|
||||
notify(notification: INotification): INotificationHandle {
|
||||
this.withNotify(notification);
|
||||
|
||||
@@ -81,7 +89,13 @@ class EmptyNotificationService implements INotificationService {
|
||||
status(message: string, options?: IStatusMessageOptions): IDisposable {
|
||||
return Disposable.None;
|
||||
}
|
||||
setDoNotDisturbMode(mode: boolean): void {
|
||||
setGlobalDoNotDisturbMode(mode: boolean): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
isSourceDoNotDisturb(source: INotificationSource): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
setSourceDoNotDisturb(source: INotificationSource, mode: boolean): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1338,7 +1338,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
if (!restoring) {
|
||||
zenModeExitInfo.transitionedToFullScreen = toggleFullScreen;
|
||||
zenModeExitInfo.transitionedToCenteredEditorLayout = !this.isMainEditorLayoutCentered() && config.centerLayout;
|
||||
zenModeExitInfo.handleNotificationsDoNotDisturbMode = !this.notificationService.isDoNotDisturbMode;
|
||||
zenModeExitInfo.handleNotificationsDoNotDisturbMode = !this.notificationService.isGlobalDoNotDisturbMode;
|
||||
zenModeExitInfo.wasVisible.sideBar = this.isVisible(Parts.SIDEBAR_PART);
|
||||
zenModeExitInfo.wasVisible.panel = this.isVisible(Parts.PANEL_PART);
|
||||
zenModeExitInfo.wasVisible.auxiliaryBar = this.isVisible(Parts.AUXILIARYBAR_PART);
|
||||
@@ -1367,7 +1367,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
}
|
||||
|
||||
if (config.silentNotifications && zenModeExitInfo.handleNotificationsDoNotDisturbMode) {
|
||||
this.notificationService.setDoNotDisturbMode(true);
|
||||
this.notificationService.setGlobalDoNotDisturbMode(true);
|
||||
}
|
||||
|
||||
if (config.centerLayout) {
|
||||
@@ -1404,7 +1404,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
if (e.affectsConfiguration(ZenModeSettings.SILENT_NOTIFICATIONS)) {
|
||||
const zenModeSilentNotifications = !!this.configurationService.getValue(ZenModeSettings.SILENT_NOTIFICATIONS);
|
||||
if (zenModeExitInfo.handleNotificationsDoNotDisturbMode) {
|
||||
this.notificationService.setDoNotDisturbMode(zenModeSilentNotifications);
|
||||
this.notificationService.setGlobalDoNotDisturbMode(zenModeSilentNotifications);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1444,7 +1444,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
}
|
||||
|
||||
if (zenModeExitInfo.handleNotificationsDoNotDisturbMode) {
|
||||
this.notificationService.setDoNotDisturbMode(false);
|
||||
this.notificationService.setGlobalDoNotDisturbMode(false);
|
||||
}
|
||||
|
||||
setLineNumbers();
|
||||
|
||||
@@ -67,10 +67,10 @@ export class NotificationsCenter extends Themable implements INotificationsCente
|
||||
private registerListeners(): void {
|
||||
this._register(this.model.onDidChangeNotification(e => this.onDidChangeNotification(e)));
|
||||
this._register(this.layoutService.onDidLayoutMainContainer(dimension => this.layout(Dimension.lift(dimension))));
|
||||
this._register(this.notificationService.onDidChangeDoNotDisturbMode(() => this.onDidChangeDoNotDisturbMode()));
|
||||
this._register(this.notificationService.onDidChangeGlobalDoNotDisturbMode(() => this.onDidChangeGlobalDoNotDisturbMode()));
|
||||
}
|
||||
|
||||
private onDidChangeDoNotDisturbMode(): void {
|
||||
private onDidChangeGlobalDoNotDisturbMode(): void {
|
||||
this.hide(); // hide the notification center when do not disturb is toggled
|
||||
}
|
||||
|
||||
|
||||
@@ -287,7 +287,7 @@ export function registerNotificationCommands(center: INotificationsCenterControl
|
||||
CommandsRegistry.registerCommand(TOGGLE_DO_NOT_DISTURB_MODE, accessor => {
|
||||
const notificationService = accessor.get(INotificationService);
|
||||
|
||||
notificationService.setDoNotDisturbMode(!notificationService.isDoNotDisturbMode);
|
||||
notificationService.setGlobalDoNotDisturbMode(!notificationService.isGlobalDoNotDisturbMode);
|
||||
});
|
||||
|
||||
// Commands for Command Palette
|
||||
|
||||
@@ -39,7 +39,7 @@ export class NotificationsStatus extends Disposable {
|
||||
private registerListeners(): void {
|
||||
this._register(this.model.onDidChangeNotification(e => this.onDidChangeNotification(e)));
|
||||
this._register(this.model.onDidChangeStatusMessage(e => this.onDidChangeStatusMessage(e)));
|
||||
this._register(this.notificationService.onDidChangeDoNotDisturbMode(() => this.updateNotificationsCenterStatusItem()));
|
||||
this._register(this.notificationService.onDidChangeGlobalDoNotDisturbMode(() => this.updateNotificationsCenterStatusItem()));
|
||||
}
|
||||
|
||||
private onDidChangeNotification(e: INotificationChangeEvent): void {
|
||||
@@ -83,7 +83,7 @@ export class NotificationsStatus extends Disposable {
|
||||
showBeak: this.isNotificationsCenterVisible
|
||||
};
|
||||
|
||||
if (this.notificationService.isDoNotDisturbMode) {
|
||||
if (this.notificationService.isGlobalDoNotDisturbMode) {
|
||||
statusProperties = {
|
||||
...statusProperties,
|
||||
text: `${notificationsInProgress > 0 || this.newNotificationsCount > 0 ? '$(bell-slash-dot)' : '$(bell-slash)'}`,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice, IStatusMessageOptions, NotificationsFilter, INotificationProgressProperties, IPromptChoiceWithMenu, NotificationPriority } from 'vs/platform/notification/common/notification';
|
||||
import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice, IStatusMessageOptions, NotificationsFilter, INotificationProgressProperties, IPromptChoiceWithMenu, NotificationPriority, INotificationSource, isNotificationSource } from 'vs/platform/notification/common/notification';
|
||||
import { toErrorMessage, isErrorWithActions } from 'vs/base/common/errorMessage';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
@@ -495,7 +495,7 @@ export class NotificationViewItem extends Disposable implements INotificationVie
|
||||
if (priority === NotificationPriority.DEFAULT && severity !== Severity.Error) {
|
||||
if (filter.global === NotificationsFilter.ERROR) {
|
||||
priority = NotificationPriority.SILENT; // filtered globally
|
||||
} else if (notification.source && typeof notification.source !== 'string' && filter.sources.has(notification.source.id)) {
|
||||
} else if (isNotificationSource(notification.source) && filter.sources.has(notification.source.id)) {
|
||||
priority = NotificationPriority.SILENT; // filtered by source
|
||||
}
|
||||
}
|
||||
@@ -537,7 +537,7 @@ export class NotificationViewItem extends Disposable implements INotificationVie
|
||||
private _sticky: boolean | undefined,
|
||||
private _priority: NotificationPriority,
|
||||
private _message: INotificationMessage,
|
||||
private _source: string | { label: string; id: string } | undefined,
|
||||
private _source: string | INotificationSource | undefined,
|
||||
progress: INotificationProgressProperties | undefined,
|
||||
actions?: INotificationActions
|
||||
) {
|
||||
|
||||
@@ -193,7 +193,7 @@ suite('ConfigurationEditing', () => {
|
||||
test('do not notify error', async () => {
|
||||
instantiationService.stub(ITextFileService, 'isDirty', true);
|
||||
const target = sinon.stub();
|
||||
instantiationService.stub(INotificationService, <INotificationService>{ prompt: target, _serviceBrand: undefined, isDoNotDisturbMode: false, onDidAddNotification: undefined!, onDidRemoveNotification: undefined!, onDidChangeDoNotDisturbMode: undefined!, notify: null!, error: null!, info: null!, warn: null!, status: null!, setDoNotDisturbMode: null! });
|
||||
instantiationService.stub(INotificationService, <INotificationService>{ prompt: target, _serviceBrand: undefined, isGlobalDoNotDisturbMode: false, onDidAddNotification: undefined!, onDidRemoveNotification: undefined!, onDidChangeGlobalDoNotDisturbMode: undefined!, onDidChangePerSourceDoNotDisturbMode: null!, notify: null!, error: null!, info: null!, warn: null!, status: null!, setGlobalDoNotDisturbMode: null!, isSourceDoNotDisturb: null!, setSourceDoNotDisturb: null! });
|
||||
try {
|
||||
await testObject.writeConfiguration(EditableConfigurationTarget.USER_LOCAL, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotNotifyError: true });
|
||||
} catch (error) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification, NeverShowAgainScope, NotificationsFilter, INeverShowAgainOptions } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification, NeverShowAgainScope, NotificationsFilter, INeverShowAgainOptions, INotificationSource } from 'vs/platform/notification/common/notification';
|
||||
import { NotificationsModel, ChoiceAction, NotificationChangeType } from 'vs/workbench/common/notifications';
|
||||
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
@@ -12,6 +12,10 @@ import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
|
||||
interface INotificationSourceDoNotDisturb extends INotificationSource {
|
||||
readonly filter: NotificationsFilter;
|
||||
}
|
||||
|
||||
export class NotificationService extends Disposable implements INotificationService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
@@ -59,33 +63,77 @@ export class NotificationService extends Disposable implements INotificationServ
|
||||
}));
|
||||
}
|
||||
|
||||
//#region Do not disturb mode
|
||||
//#region Do not disturb mode (global)
|
||||
|
||||
static readonly DND_SETTINGS_KEY = 'notifications.doNotDisturbMode';
|
||||
private static readonly GLOBAL_DND_SETTINGS_KEY = 'notifications.doNotDisturbMode';
|
||||
|
||||
private readonly _onDidChangeDoNotDisturbMode = this._register(new Emitter<void>());
|
||||
readonly onDidChangeDoNotDisturbMode = this._onDidChangeDoNotDisturbMode.event;
|
||||
private readonly _onDidChangeGlobalDoNotDisturbMode = this._register(new Emitter<void>());
|
||||
readonly onDidChangeGlobalDoNotDisturbMode = this._onDidChangeGlobalDoNotDisturbMode.event;
|
||||
|
||||
private _isDoNotDisturbMode = this.storageService.getBoolean(NotificationService.DND_SETTINGS_KEY, StorageScope.APPLICATION, false);
|
||||
get isDoNotDisturbMode() { return this._isDoNotDisturbMode; }
|
||||
private _isGlobalDoNotDisturbMode = this.storageService.getBoolean(NotificationService.GLOBAL_DND_SETTINGS_KEY, StorageScope.APPLICATION, false);
|
||||
get isGlobalDoNotDisturbMode() { return this._isGlobalDoNotDisturbMode; }
|
||||
|
||||
setDoNotDisturbMode(enabled: boolean): void {
|
||||
if (this._isDoNotDisturbMode === enabled) {
|
||||
setGlobalDoNotDisturbMode(enabled: boolean): void {
|
||||
if (this._isGlobalDoNotDisturbMode === enabled) {
|
||||
return; // no change
|
||||
}
|
||||
|
||||
this.storageService.store(NotificationService.DND_SETTINGS_KEY, enabled, StorageScope.APPLICATION, StorageTarget.MACHINE);
|
||||
this._isDoNotDisturbMode = enabled;
|
||||
// Store into model and persist
|
||||
this._isGlobalDoNotDisturbMode = enabled;
|
||||
this.storageService.store(NotificationService.GLOBAL_DND_SETTINGS_KEY, enabled, StorageScope.APPLICATION, StorageTarget.MACHINE);
|
||||
|
||||
// Toggle via filter
|
||||
// Update model
|
||||
this.updateDoNotDisturbFilters();
|
||||
|
||||
// Events
|
||||
this._onDidChangeDoNotDisturbMode.fire();
|
||||
this._onDidChangeGlobalDoNotDisturbMode.fire();
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Do not disturb mode (per-source)
|
||||
|
||||
private static readonly PER_SOURCE_DND_SETTINGS_KEY = 'notifications.perSourceDoNotDisturbMode';
|
||||
|
||||
private readonly _onDidChangePerSourceDoNotDisturbMode = this._register(new Emitter<INotificationSource>());
|
||||
readonly onDidChangePerSourceDoNotDisturbMode = this._onDidChangePerSourceDoNotDisturbMode.event;
|
||||
|
||||
private readonly mapSourceIdToDoNotDisturb: Map<string /** source id */, INotificationSourceDoNotDisturb> = (() => {
|
||||
const map = new Map<string, INotificationSourceDoNotDisturb>();
|
||||
|
||||
for (const sourceFilter of this.storageService.getObject<INotificationSourceDoNotDisturb[]>(NotificationService.PER_SOURCE_DND_SETTINGS_KEY, StorageScope.APPLICATION, Object.create(null))) {
|
||||
map.set(sourceFilter.id, sourceFilter);
|
||||
}
|
||||
|
||||
return map;
|
||||
})();
|
||||
|
||||
isSourceDoNotDisturb(source: INotificationSource): boolean {
|
||||
return this.mapSourceIdToDoNotDisturb.get(source.id)?.filter === NotificationsFilter.ERROR;
|
||||
}
|
||||
|
||||
setSourceDoNotDisturb(source: INotificationSource, mode: boolean): void {
|
||||
const existing = this.mapSourceIdToDoNotDisturb.get(source.id);
|
||||
if (existing?.filter === (mode ? NotificationsFilter.ERROR : NotificationsFilter.OFF)) {
|
||||
return; // no change
|
||||
}
|
||||
|
||||
// Store into model and persist
|
||||
this.mapSourceIdToDoNotDisturb.set(source.id, { id: source.id, label: source.label, filter: mode ? NotificationsFilter.ERROR : NotificationsFilter.OFF });
|
||||
this.storageService.store(NotificationService.PER_SOURCE_DND_SETTINGS_KEY, JSON.stringify([...this.mapSourceIdToDoNotDisturb.values()]), StorageScope.APPLICATION, StorageTarget.MACHINE);
|
||||
|
||||
// Update model
|
||||
this.updateDoNotDisturbFilters();
|
||||
|
||||
// Events
|
||||
this._onDidChangePerSourceDoNotDisturbMode.fire(source);
|
||||
}
|
||||
|
||||
private updateDoNotDisturbFilters(): void {
|
||||
this.model.setFilter({ global: this._isDoNotDisturbMode ? NotificationsFilter.ERROR : NotificationsFilter.OFF });
|
||||
this.model.setFilter({
|
||||
global: this._isGlobalDoNotDisturbMode ? NotificationsFilter.ERROR : NotificationsFilter.OFF,
|
||||
sources: new Map([...this.mapSourceIdToDoNotDisturb.values()].map(source => [source.id, source.filter]))
|
||||
});
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -11,7 +11,7 @@ import { IProgressService, IProgressOptions, IProgressStep, ProgressLocation, IP
|
||||
import { StatusbarAlignment, IStatusbarService, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/workbench/services/statusbar/browser/statusbar';
|
||||
import { DeferredPromise, RunOnceScheduler, timeout } from 'vs/base/common/async';
|
||||
import { ProgressBadge, IActivityService } from 'vs/workbench/services/activity/common/activity';
|
||||
import { INotificationService, Severity, INotificationHandle, NotificationPriority } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationService, Severity, INotificationHandle, NotificationPriority, isNotificationSource } from 'vs/platform/notification/common/notification';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
@@ -68,8 +68,16 @@ export class ProgressService extends Disposable implements IProgressService {
|
||||
}
|
||||
|
||||
switch (location) {
|
||||
case ProgressLocation.Notification:
|
||||
return this.withNotificationProgress({ ...options, location, priority: this.notificationService.isDoNotDisturbMode ? NotificationPriority.SILENT : undefined }, task, onDidCancel);
|
||||
case ProgressLocation.Notification: {
|
||||
let priority: NotificationPriority | undefined = undefined;
|
||||
if (this.notificationService.isGlobalDoNotDisturbMode) {
|
||||
priority = NotificationPriority.SILENT;
|
||||
} else if (isNotificationSource(options.source) && this.notificationService.isSourceDoNotDisturb(options.source)) {
|
||||
priority = NotificationPriority.SILENT;
|
||||
}
|
||||
|
||||
return this.withNotificationProgress({ ...options, location, priority }, task, onDidCancel);
|
||||
}
|
||||
case ProgressLocation.Window: {
|
||||
const type = (options as IProgressWindowOptions).type;
|
||||
if ((options as IProgressWindowOptions).command) {
|
||||
|
||||
Reference in New Issue
Block a user