提交 4f9f4c3c 编写于 作者: B Benjamin Pasero

fix #72417

上级 b8974b05
......@@ -37,6 +37,19 @@ export interface INotificationProperties {
neverShowAgain?: INeverShowAgainOptions;
}
export enum NeverShowAgainScope {
/**
* Will never show this notification on the current workspace again.
*/
WORKSPACE,
/**
* Will never show this notification on any workspace again.
*/
GLOBAL
}
export interface INeverShowAgainOptions {
/**
......@@ -49,6 +62,12 @@ export interface INeverShowAgainOptions {
* make it a secondary action instead.
*/
isSecondary?: boolean;
/**
* Wether to persist the choice in the current workspace or for all workspaces. By
* default it will be persisted for all workspaces.
*/
scope?: NeverShowAgainScope;
}
export interface INotification extends INotificationProperties {
......
......@@ -236,7 +236,6 @@ class ResolveSaveConflictAction extends Action {
@IEditorService private readonly editorService: IEditorService,
@INotificationService private readonly notificationService: INotificationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IStorageService private readonly storageService: IStorageService,
@IEnvironmentService private readonly environmentService: IEnvironmentService
) {
super('workbench.files.action.resolveConflict', nls.localize('compareChanges', "Compare"));
......@@ -250,21 +249,15 @@ class ResolveSaveConflictAction extends Action {
await TextFileContentProvider.open(resource, CONFLICT_RESOLUTION_SCHEME, editorLabel, this.editorService, { pinned: true });
if (this.storageService.getBoolean(LEARN_MORE_DIRTY_WRITE_IGNORE_KEY, StorageScope.GLOBAL)) {
return; // return if this message is ignored
}
// Show additional help how to resolve the save conflict
const primaryActions: IAction[] = [
this.instantiationService.createInstance(ResolveConflictLearnMoreAction)
];
const secondaryActions: IAction[] = [
this.instantiationService.createInstance(DoNotShowResolveConflictLearnMoreAction)
];
const actions: INotificationActions = { primary: primaryActions, secondary: secondaryActions };
const handle = this.notificationService.notify({ severity: Severity.Info, message: conflictEditorHelp, actions });
Event.once(handle.onDidClose)(() => { dispose(primaryActions); dispose(secondaryActions); });
const actions: INotificationActions = { primary: [this.instantiationService.createInstance(ResolveConflictLearnMoreAction)] };
const handle = this.notificationService.notify({
severity: Severity.Info,
message: conflictEditorHelp,
actions,
neverShowAgain: { id: LEARN_MORE_DIRTY_WRITE_IGNORE_KEY, isSecondary: true }
});
Event.once(handle.onDidClose)(() => dispose(actions.primary!));
pendingResolveSaveConflictMessages.push(handle);
}
......
......@@ -68,8 +68,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
}
private onDidInstallExtension(e: DidInstallExtensionEvent): void {
const donotAskUpdateKey = 'langugage.update.donotask';
if (!this.storageService.getBoolean(donotAskUpdateKey, StorageScope.GLOBAL) && e.local && e.operation === InstallOperation.Install && e.local.manifest.contributes && e.local.manifest.contributes.localizations && e.local.manifest.contributes.localizations.length) {
if (e.local && e.operation === InstallOperation.Install && e.local.manifest.contributes && e.local.manifest.contributes.localizations && e.local.manifest.contributes.localizations.length) {
const locale = e.local.manifest.contributes.localizations[0].languageId;
if (platform.language !== locale) {
const updateAndRestart = platform.locale !== locale;
......@@ -83,12 +82,11 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
const updatePromise = updateAndRestart ? this.jsonEditingService.write(this.environmentService.localeResource, { key: 'locale', value: locale }, true) : Promise.resolve(undefined);
updatePromise.then(() => this.windowsService.relaunch({}), e => this.notificationService.error(e));
}
}, {
label: localize('neverAgain', "Don't Show Again"),
isSecondary: true,
run: () => this.storageService.store(donotAskUpdateKey, true, StorageScope.GLOBAL)
}],
{ sticky: true }
{
sticky: true,
neverShowAgain: { id: 'langugage.update.donotask', isSecondary: true }
}
);
}
}
......@@ -302,4 +300,4 @@ ExtensionsRegistry.registerExtensionPoint({
}
}
}
});
\ No newline at end of file
});
......@@ -8,9 +8,8 @@ import { IFileService, IResolveFileResult, IFileStat } from 'vs/platform/files/c
import { IWorkspaceContextService, WorkbenchState, IWorkspace } from 'vs/platform/workspace/common/workspace';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IWindowService, IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { INotificationService, IPromptChoice } from 'vs/platform/notification/common/notification';
import { INotificationService, NeverShowAgainScope, INeverShowAgainOptions } from 'vs/platform/notification/common/notification';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ITextFileService, ITextFileContent } from 'vs/workbench/services/textfile/common/textfiles';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
......@@ -22,8 +21,6 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IWorkspaceStatsService, Tags } from 'vs/workbench/contrib/stats/common/workspaceStats';
import { getHashedRemotesFromConfig } from 'vs/workbench/contrib/stats/electron-browser/workspaceStats';
const DISABLE_WORKSPACE_PROMPT_KEY = 'workspaces.dontPromptToOpen';
const ModulesToLookFor = [
// Packages that suggest a node server
'express',
......@@ -103,7 +100,6 @@ export class WorkspaceStatsService implements IWorkspaceStatsService {
@IWindowService private readonly windowService: IWindowService,
@INotificationService private readonly notificationService: INotificationService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IStorageService private readonly storageService: IStorageService,
@ITextFileService private readonly textFileService: ITextFileService
) { }
......@@ -449,15 +445,7 @@ export class WorkspaceStatsService implements IWorkspaceStatsService {
}
private doHandleWorkspaceFiles(folder: URI, workspaces: string[]): void {
if (this.storageService.getBoolean(DISABLE_WORKSPACE_PROMPT_KEY, StorageScope.WORKSPACE)) {
return; // prompt disabled by user
}
const doNotShowAgain: IPromptChoice = {
label: localize('never again', "Don't Show Again"),
isSecondary: true,
run: () => this.storageService.store(DISABLE_WORKSPACE_PROMPT_KEY, true, StorageScope.WORKSPACE)
};
const neverShowAgain: INeverShowAgainOptions = { id: 'workspaces.dontPromptToOpen', scope: NeverShowAgainScope.WORKSPACE, isSecondary: true };
// Prompt to open one workspace
if (workspaces.length === 1) {
......@@ -466,7 +454,7 @@ export class WorkspaceStatsService implements IWorkspaceStatsService {
this.notificationService.prompt(Severity.Info, localize('workspaceFound', "This folder contains a workspace file '{0}'. Do you want to open it? [Learn more]({1}) about workspace files.", workspaceFile, 'https://go.microsoft.com/fwlink/?linkid=2025315'), [{
label: localize('openWorkspace', "Open Workspace"),
run: () => this.windowService.openWindow([{ workspaceUri: joinPath(folder, workspaceFile) }])
}, doNotShowAgain]);
}], { neverShowAgain });
}
// Prompt to select a workspace from many
......@@ -482,7 +470,7 @@ export class WorkspaceStatsService implements IWorkspaceStatsService {
}
});
}
}, doNotShowAgain]);
}], { neverShowAgain });
}
}
......
......@@ -11,7 +11,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { ITerminalConfiguration, ITerminalFont, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro, IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal';
import Severity from 'vs/base/common/severity';
import { Terminal as XTermTerminal } from 'xterm';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { INotificationService, NeverShowAgainScope } from 'vs/platform/notification/common/notification';
import { IBrowserTerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminal';
import { Emitter, Event } from 'vs/base/common/event';
import { basename } from 'vs/base/common/path';
......@@ -254,7 +254,6 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
return r;
}
private readonly NO_RECOMMENDATIONS_KEY = 'terminalConfigHelper/launchRecommendationsIgnore';
private recommendationsShown = false;
public async showRecommendations(shellLaunchConfig: IShellLaunchConfig): Promise<void> {
......@@ -264,10 +263,6 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
this.recommendationsShown = true;
if (platform.isWindows && shellLaunchConfig.executable && basename(shellLaunchConfig.executable).toLowerCase() === 'wsl.exe') {
if (this._storageService.getBoolean(this.NO_RECOMMENDATIONS_KEY, StorageScope.WORKSPACE, false)) {
return;
}
if (! await this.isExtensionInstalled('ms-vscode-remote.remote-wsl')) {
this._notificationService.prompt(
Severity.Info,
......@@ -276,16 +271,10 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
"Check out the 'Visual Studio Code Remote - WSL' extension for a great development experience in WSL. Click [here]({0}) to learn more.",
'https://go.microsoft.com/fwlink/?linkid=2097212'
),
[
{
label: nls.localize('doNotShowAgain', "Don't Show Again"),
run: () => {
this._storageService.store(this.NO_RECOMMENDATIONS_KEY, true, StorageScope.WORKSPACE);
}
}
],
[],
{
sticky: true
sticky: true,
neverShowAgain: { id: 'terminalConfigHelper/launchRecommendationsIgnore', scope: NeverShowAgainScope.WORKSPACE }
}
);
}
......
......@@ -19,7 +19,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { IUpdateService, State as UpdateState, StateType, IUpdate } from 'vs/platform/update/common/update';
import * as semver from 'semver-umd';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { INotificationService, INotificationHandle, Severity } from 'vs/platform/notification/common/notification';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { ReleaseNotesManager } from './releaseNotesEditor';
......@@ -162,32 +162,8 @@ export class ProductContribution implements IWorkbenchContribution {
}
}
class NeverShowAgain {
private readonly key: string;
readonly action = new Action(`neverShowAgain:${this.key}`, nls.localize('neveragain', "Don't Show Again"), undefined, true, (notification: INotificationHandle) => {
// Hide notification
notification.close();
this.storageService.store(this.key, true, StorageScope.GLOBAL);
return Promise.resolve(true);
});
constructor(key: string, @IStorageService private readonly storageService: IStorageService) {
this.key = `neverShowAgain:${key}`;
}
shouldShow(): boolean {
return !this.storageService.getBoolean(this.key, StorageScope.GLOBAL, false);
}
}
export class Win3264BitContribution implements IWorkbenchContribution {
private static readonly KEY = 'update/win32-64bits';
private static readonly URL = 'https://code.visualstudio.com/updates/v1_15#_windows-64-bit';
private static readonly INSIDER_URL = 'https://github.com/Microsoft/vscode-docs/blob/vnext/release-notes/v1_15.md#windows-64-bit';
......@@ -200,28 +176,18 @@ export class Win3264BitContribution implements IWorkbenchContribution {
return;
}
const neverShowAgain = new NeverShowAgain(Win3264BitContribution.KEY, storageService);
if (!neverShowAgain.shouldShow()) {
return;
}
const url = product.quality === 'insider'
? Win3264BitContribution.INSIDER_URL
: Win3264BitContribution.URL;
const handle = notificationService.prompt(
notificationService.prompt(
severity.Info,
nls.localize('64bitisavailable', "{0} for 64-bit Windows is now available! Click [here]({1}) to learn more.", product.nameShort, url),
[{
label: nls.localize('neveragain', "Don't Show Again"),
isSecondary: true,
run: () => {
neverShowAgain.action.run(handle);
neverShowAgain.action.dispose();
}
}],
{ sticky: true }
[],
{
sticky: true,
neverShowAgain: { id: 'neverShowAgain:update/win32-64bits', isSecondary: true }
}
);
}
}
......@@ -396,23 +362,13 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu
}
// windows fast updates (target === system)
const neverShowAgain = new NeverShowAgain('update/win32-fast-updates', this.storageService);
if (!neverShowAgain.shouldShow()) {
return;
}
const handle = this.notificationService.prompt(
this.notificationService.prompt(
severity.Info,
nls.localize('updateInstalling', "{0} {1} is being installed in the background; we'll let you know when it's done.", product.nameLong, update.productVersion),
[{
label: nls.localize('neveragain', "Don't Show Again"),
isSecondary: true,
run: () => {
neverShowAgain.action.run(handle);
neverShowAgain.action.dispose();
}
}]
[],
{
neverShowAgain: { id: 'neverShowAgain:update/win32-fast-updates', isSecondary: true }
}
);
}
......
......@@ -13,8 +13,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { ResourceMap } from 'vs/base/common/map';
import { onUnexpectedError } from 'vs/base/common/errors';
import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { INotificationService, Severity, NeverShowAgainScope } from 'vs/platform/notification/common/notification';
import { localize } from 'vs/nls';
import { FileService } from 'vs/platform/files/common/fileService';
......@@ -26,8 +25,7 @@ export class WorkspaceWatcher extends Disposable {
@IFileService private readonly fileService: FileService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@INotificationService private readonly notificationService: INotificationService,
@IStorageService private readonly storageService: IStorageService
@INotificationService private readonly notificationService: INotificationService
) {
super();
......@@ -73,38 +71,34 @@ export class WorkspaceWatcher extends Disposable {
onUnexpectedError(msg);
// Detect if we run < .NET Framework 4.5
if (msg.indexOf('System.MissingMethodException') >= 0 && !this.storageService.getBoolean('ignoreNetVersionError', StorageScope.WORKSPACE)) {
if (msg.indexOf('System.MissingMethodException') >= 0) {
this.notificationService.prompt(
Severity.Warning,
localize('netVersionError', "The Microsoft .NET Framework 4.5 is required. Please follow the link to install it."),
[{
label: localize('installNet', "Download .NET Framework 4.5"),
run: () => window.open('https://go.microsoft.com/fwlink/?LinkId=786533')
},
{
label: localize('neverShowAgain', "Don't Show Again"),
isSecondary: true,
run: () => this.storageService.store('ignoreNetVersionError', true, StorageScope.WORKSPACE)
}],
{ sticky: true }
{
sticky: true,
neverShowAgain: { id: 'ignoreNetVersionError', isSecondary: true, scope: NeverShowAgainScope.WORKSPACE }
}
);
}
// Detect if we run into ENOSPC issues
if (msg.indexOf('ENOSPC') >= 0 && !this.storageService.getBoolean('ignoreEnospcError', StorageScope.WORKSPACE)) {
if (msg.indexOf('ENOSPC') >= 0) {
this.notificationService.prompt(
Severity.Warning,
localize('enospcError', "Unable to watch for file changes in this large workspace. Please follow the instructions link to resolve this issue."),
[{
label: localize('learnMore', "Instructions"),
run: () => window.open('https://go.microsoft.com/fwlink/?linkid=867693')
},
{
label: localize('neverShowAgain', "Don't Show Again"),
isSecondary: true,
run: () => this.storageService.store('ignoreEnospcError', true, StorageScope.WORKSPACE)
}],
{ sticky: true }
{
sticky: true,
neverShowAgain: { id: 'ignoreEnospcError', isSecondary: true, scope: NeverShowAgainScope.WORKSPACE }
}
);
}
}
......@@ -157,4 +151,4 @@ export class WorkspaceWatcher extends Disposable {
}
}
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(WorkspaceWatcher, LifecyclePhase.Restored);
\ No newline at end of file
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(WorkspaceWatcher, LifecyclePhase.Restored);
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification } from 'vs/platform/notification/common/notification';
import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification, NeverShowAgainScope } from 'vs/platform/notification/common/notification';
import { INotificationsModel, NotificationsModel, ChoiceAction } from 'vs/workbench/common/notifications';
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { Event } from 'vs/base/common/event';
......@@ -63,11 +63,12 @@ export class NotificationService extends Disposable implements INotificationServ
// Handle neverShowAgain option accordingly
let handle: INotificationHandle;
if (notification.neverShowAgain) {
const scope = notification.neverShowAgain.scope === NeverShowAgainScope.WORKSPACE ? StorageScope.WORKSPACE : StorageScope.GLOBAL;
// If the user already picked to not show the notification
// again, we return with a no-op notification here
const id = notification.neverShowAgain.id;
if (this.storageService.getBoolean(id, StorageScope.GLOBAL)) {
if (this.storageService.getBoolean(id, scope)) {
return new NoOpNotification();
}
......@@ -80,7 +81,7 @@ export class NotificationService extends Disposable implements INotificationServ
handle.close();
// Remember choice
this.storageService.store(id, true, StorageScope.GLOBAL);
this.storageService.store(id, true, scope);
return Promise.resolve();
}));
......@@ -110,17 +111,18 @@ export class NotificationService extends Disposable implements INotificationServ
// Handle neverShowAgain option accordingly
if (options && options.neverShowAgain) {
const scope = options.neverShowAgain.scope === NeverShowAgainScope.WORKSPACE ? StorageScope.WORKSPACE : StorageScope.GLOBAL;
// If the user already picked to not show the notification
// again, we return with a no-op notification here
const id = options.neverShowAgain.id;
if (this.storageService.getBoolean(id, StorageScope.GLOBAL)) {
if (this.storageService.getBoolean(id, scope)) {
return new NoOpNotification();
}
const neverShowAgainChoice = {
label: nls.localize('neverShowAgain', "Don't Show Again"),
run: () => this.storageService.store(id, true, StorageScope.GLOBAL),
run: () => this.storageService.store(id, true, scope),
isSecondary: options.neverShowAgain.isSecondary
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册