提交 a1a5ad0a 编写于 作者: B Benjamin Pasero

Message service show action buttons in reverse order (fixes #11311)

上级 4f21084c
......@@ -92,14 +92,14 @@ export class MessageList {
public showMessage(severity: Severity, message: IMessageWithAction): () => void;
public showMessage(severity: Severity, message: any): () => void {
if (Array.isArray(message)) {
let closeFns: Function[] = [];
const closeFns: Function[] = [];
message.forEach((msg: any) => closeFns.push(this.showMessage(severity, msg)));
return () => closeFns.forEach((fn) => fn());
}
// Return only if we are unable to extract a message text
let messageText = this.getMessageText(message);
const messageText = this.getMessageText(message);
if (!messageText || typeof messageText !== 'string') {
return () => {/* empty */ };
}
......@@ -162,7 +162,7 @@ export class MessageList {
}
private renderMessages(animate: boolean, delta: number): void {
let container = withElementById(this.containerElementId);
const container = withElementById(this.containerElementId);
if (!container) {
return; // Cannot build container for messages yet, return
}
......@@ -182,7 +182,7 @@ export class MessageList {
// Render Messages as List Items
$(this.messageListContainer).ul({ 'class': 'message-list' }, (ul: Builder) => {
let messages = this.prepareMessages();
const messages = this.prepareMessages();
if (messages.length > 0) {
this._onMessagesShowing.fire();
} else {
......@@ -207,14 +207,14 @@ export class MessageList {
container.li({ class: 'message-list-entry message-list-entry-with-action' }, (li) => {
// Actions (if none provided, add one default action to hide message)
let messageActions = this.getMessageActions(message);
const messageActions = this.getMessageActions(message);
li.div({ class: 'actions-container' }, (actionContainer) => {
for (let i = messageActions.length - 1; i >= 0; i--) {
let action = messageActions[i];
for (let i = 0; i < messageActions.length; i++) {
const action = messageActions[i];
actionContainer.div({ class: 'message-action' }, (div) => {
div.a({ class: 'action-button', tabindex: '0', role: 'button' }).text(action.label).on([DOM.EventType.CLICK, DOM.EventType.KEY_DOWN], (e) => {
if (e instanceof KeyboardEvent) {
let event = new StandardKeyboardEvent(e);
const event = new StandardKeyboardEvent(e);
if (!event.equals(CommonKeybindings.ENTER) && !event.equals(CommonKeybindings.SPACE)) {
return; // Only handle Enter/Escape for keyboard access
}
......@@ -241,17 +241,17 @@ export class MessageList {
});
// Text
let text = message.text.substr(0, this.options.maxMessageLength);
const text = message.text.substr(0, this.options.maxMessageLength);
li.div({ class: 'message-left-side' }, (div) => {
div.addClass('message-overflow-ellipsis');
// Severity indicator
let sev = message.severity;
let label = (sev === Severity.Error) ? nls.localize('error', "Error") : (sev === Severity.Warning) ? nls.localize('warning', "Warn") : nls.localize('info', "Info");
const sev = message.severity;
const label = (sev === Severity.Error) ? nls.localize('error', "Error") : (sev === Severity.Warning) ? nls.localize('warning', "Warn") : nls.localize('info', "Info");
$().span({ class: 'message-left-side severity ' + ((sev === Severity.Error) ? 'app-error' : (sev === Severity.Warning) ? 'app-warning' : 'app-info'), text: label }).appendTo(div);
// Error message
let messageContentElement: HTMLElement = <any>htmlRenderer.renderHtml({
const messageContentElement: HTMLElement = <any>htmlRenderer.renderHtml({
tagName: 'span',
className: 'message-left-side',
formattedText: text
......@@ -282,12 +282,12 @@ export class MessageList {
private prepareMessages(): IMessageEntry[] {
// Aggregate Messages by text to reduce their count
let messages: IMessageEntry[] = [];
let handledMessages: { [message: string]: number; } = {};
const messages: IMessageEntry[] = [];
const handledMessages: { [message: string]: number; } = {};
let offset = 0;
for (let i = 0; i < this.messages.length; i++) {
let message = this.messages[i];
const message = this.messages[i];
if (types.isUndefinedOrNull(handledMessages[message.text])) {
message.count = 1;
messages.push(message);
......@@ -335,7 +335,7 @@ export class MessageList {
let messageFound = false;
for (let i = 0; i < this.messages.length; i++) {
let message = this.messages[i];
const message = this.messages[i];
let hide = false;
// Hide specific message
......@@ -373,7 +373,7 @@ export class MessageList {
let counter = 0;
for (let i = 0; i < this.messages.length; i++) {
let message = this.messages[i];
const message = this.messages[i];
// Only purge infos and warnings and only if they are not providing actions
if (message.severity !== Severity.Error && !message.actions) {
......
......@@ -49,7 +49,7 @@ export class MainThreadMessageService extends MainThreadMessageServiceShape {
});
if (!hasCloseAffordance) {
actions.unshift(new MessageItemAction('__close', nls.localize('close', "Close"), undefined));
actions.push(new MessageItemAction('__close', nls.localize('close', "Close"), undefined));
}
messageHide = this._messageService.show(severity, {
......
......@@ -148,19 +148,19 @@ export class OpenGlobalSettingsAction extends BaseOpenSettingsAction {
this.messageService.show(Severity.Info, {
message: nls.localize('workspaceHasSettings', "The currently opened folder contains workspace settings that may override user settings"),
actions: [
CloseAction,
new Action('neverShowAgain', nls.localize('neverShowAgain', "Don't show again"), null, true, () => {
this.storageService.store(OpenGlobalSettingsAction.SETTINGS_INFO_IGNORE_KEY, true, StorageScope.WORKSPACE);
return TPromise.as(true);
}),
new Action('open.workspaceSettings', nls.localize('openWorkspaceSettings', "Open Workspace Settings"), null, true, () => {
let editorCount = this.editorService.getVisibleEditors().length;
return this.editorService.createInput({ resource: this.contextService.toResource(WORKSPACE_CONFIG_DEFAULT_PATH) }).then((typedInput) => {
return this.editorService.openEditor(typedInput, { pinned: true }, editorCount === 2 ? Position.RIGHT : editorCount === 1 ? Position.CENTER : void 0);
});
})
}),
new Action('neverShowAgain', nls.localize('neverShowAgain', "Don't show again"), null, true, () => {
this.storageService.store(OpenGlobalSettingsAction.SETTINGS_INFO_IGNORE_KEY, true, StorageScope.WORKSPACE);
return TPromise.as(true);
}),
CloseAction
]
});
}
......
......@@ -228,10 +228,10 @@ function handleCommandDeprecations(): void {
messageService.show(Severity.Warning, {
message: nls.localize('commandDeprecated', "Command **{0}** has been removed. You can use **{1}** instead", deprecatedCommandId, newCommandId),
actions: [
CloseAction,
new Action('openKeybindings', nls.localize('openKeybindings', "Configure Keyboard Shortcuts"), null, true, () => {
return commandService.executeCommand('workbench.action.openGlobalKeybindings');
})
}),
CloseAction
]
});
},
......
......@@ -59,14 +59,14 @@ export class Update {
ipc.on('vscode:update-downloaded', (event, update: IUpdate) => {
this.messageService.show(severity.Info, {
message: nls.localize('updateAvailable', "{0} will be updated after it restarts.", product.nameLong),
actions: [ShowReleaseNotesAction(product.releaseNotesUrl), NotNowAction, ApplyUpdateAction]
actions: [ApplyUpdateAction, NotNowAction, ShowReleaseNotesAction(product.releaseNotesUrl)]
});
});
ipc.on('vscode:update-available', (event, url: string) => {
this.messageService.show(severity.Info, {
message: nls.localize('thereIsUpdateAvailable', "There is an available update."),
actions: [ShowReleaseNotesAction(product.releaseNotesUrl), NotNowAction, DownloadAction(url)]
actions: [DownloadAction(url), NotNowAction, ShowReleaseNotesAction(product.releaseNotesUrl)]
});
});
......
......@@ -78,8 +78,8 @@ class InstallAction extends Action {
return this.editorService.openEditor(input).then(() => {
const message = nls.localize('again', "Please remove the '{0}' alias from '{1}' before continuing.", product.applicationName, file);
const actions = [
new Action('cancel', nls.localize('cancel', "Cancel")),
new Action('continue', nls.localize('continue', "Continue"), '', true, () => this.run())
new Action('continue', nls.localize('continue', "Continue"), '', true, () => this.run()),
new Action('cancel', nls.localize('cancel', "Cancel"))
];
this.messageService.show(Severity.Info, { message, actions });
......@@ -128,7 +128,6 @@ class InstallAction extends Action {
return new TPromise<void>((c, e) => {
const message = nls.localize('warnEscalation', "Code will now prompt with 'osascript' for Administrator privileges to install the shell command.");
const actions = [
new Action('cancel2', nls.localize('cancel2', "Cancel"), '', true, () => { e(new Error(nls.localize('aborted', "Aborted"))); return null; }),
new Action('ok', nls.localize('ok', "OK"), '', true, () => {
const command = 'osascript -e "do shell script \\"mkdir -p /usr/local/bin && chown \\" & (do shell script (\\"whoami\\")) & \\" /usr/local/bin\\" with administrator privileges"';
......@@ -137,7 +136,8 @@ class InstallAction extends Action {
.done(c, e);
return null;
})
}),
new Action('cancel2', nls.localize('cancel2', "Cancel"), '', true, () => { e(new Error(nls.localize('aborted', "Aborted"))); return null; })
];
this.messageService.show(Severity.Info, { message, actions });
......@@ -211,7 +211,7 @@ class DarwinCLIHelper implements IWorkbenchContribution {
messageService.show(Severity.Info, nls.localize('laterInfo', "Remember you can always run the '{0}' action from the Command Palette.", installAction.label));
return null;
});
const actions = [later, now];
const actions = [now, later];
messageService.show(Severity.Info, { message, actions });
}
......
......@@ -553,7 +553,7 @@ export class DebugService implements debug.IDebugService {
if (!this.configurationManager.adapter) {
return configuration.type ? TPromise.wrapError(new Error(nls.localize('debugTypeNotSupported', "Configured debug type '{0}' is not supported.", configuration.type)))
: TPromise.wrapError(errors.create(nls.localize('debugTypeMissing', "Missing property 'type' for the chosen launch configuration."),
{ actions: [CloseAction, this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL)] }));
{ actions: [this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL), CloseAction] }));
}
return this.runPreLaunchTask(configuration.preLaunchTask).then((taskSummary: ITaskSummary) => {
......@@ -568,10 +568,10 @@ export class DebugService implements debug.IDebugService {
message: errorCount > 1 ? nls.localize('preLaunchTaskErrors', "Build errors have been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) :
errorCount === 1 ? nls.localize('preLaunchTaskError', "Build error has been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) :
nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", configuration.preLaunchTask, taskSummary.exitCode),
actions: [CloseAction, new Action('debug.continue', nls.localize('debugAnyway', "Debug Anyway"), null, true, () => {
actions: [new Action('debug.continue', nls.localize('debugAnyway', "Debug Anyway"), null, true, () => {
this.messageService.hideAll();
return this.doCreateSession(configuration);
})]
}), CloseAction]
});
}, (err: TaskError) => {
if (err.code !== TaskErrors.NotConfigured) {
......@@ -580,7 +580,7 @@ export class DebugService implements debug.IDebugService {
this.messageService.show(err.severity, {
message: err.message,
actions: [CloseAction, this.taskService.configureAction()]
actions: [this.taskService.configureAction(), CloseAction]
});
});
}))));
......@@ -704,9 +704,9 @@ export class DebugService implements debug.IDebugService {
if (filteredTasks.length !== 1) {
return TPromise.wrapError(errors.create(nls.localize('DebugTaskNotFound', "Could not find the preLaunchTask \'{0}\'.", taskName), {
actions: [
CloseAction,
this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL),
this.taskService.configureAction(),
this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL)
CloseAction
]
}));
}
......
......@@ -83,11 +83,11 @@ class EncodeDecodeDataUrlAction extends EmmetEditorAction {
const message = nls.localize('warnEscalation', "File **{0}** already exists. Do you want to overwrite the existing file?", this.imageFilePath);
const actions = [
new Action('cancel', nls.localize('cancel', "Cancel"), '', true),
new Action('ok', nls.localize('ok', "OK"), '', true, () => {
this.encodeDecode(ctx, this.imageFilePath);
return null;
})
}),
new Action('cancel', nls.localize('cancel', "Cancel"), '', true)
];
messageService.show(Severity.Warning, { message, actions });
});
......
......@@ -125,7 +125,7 @@ export class ExtensionTipsService implements IExtensionTipsService {
this.messageService.show(Severity.Info, {
message,
actions: [CloseAction, neverAgainAction, recommendationsAction]
actions: [recommendationsAction, neverAgainAction, CloseAction]
});
});
});
......
......@@ -97,7 +97,7 @@ export class UninstallAction extends Action {
return this.extensionsWorkbenchService.uninstall(this.extension).then(() => {
this.messageService.show(severity.Info, {
message: localize('postUninstallMessage', "{0} was successfully uninstalled. Restart to deactivate it.", this.extension.displayName),
actions: [LaterAction, this.instantiationService.createInstance(ReloadWindowAction, ReloadWindowAction.ID, localize('restartNow', "Restart Now"))]
actions: [this.instantiationService.createInstance(ReloadWindowAction, ReloadWindowAction.ID, localize('restartNow', "Restart Now")), LaterAction]
});
});
}
......
......@@ -344,8 +344,8 @@ export class ExtensionsViewlet extends Viewlet implements IExtensionsViewlet {
if (!/ECONNREFUSED/.test(message)) {
const error = createError(localize('suggestProxyError', "Marketplace returned 'ECONNREFUSED'. Please check the 'http.proxy' setting."), {
actions: [
CloseAction,
this.instantiationService.createInstance(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL)
this.instantiationService.createInstance(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL),
CloseAction
]
});
......
......@@ -175,7 +175,6 @@ export class TextFileEditor extends BaseTextEditor {
if ((<IFileOperationResult>error).fileOperationResult === FileOperationResult.FILE_NOT_FOUND && paths.isValidBasename(paths.basename((<FileEditorInput>input).getResource().fsPath))) {
return TPromise.wrapError(errors.create(errors.toErrorMessage(error), {
actions: [
CancelAction,
new Action('workbench.files.action.createMissingFile', nls.localize('createFile', "Create File"), null, true, () => {
return this.fileService.updateContent((<FileEditorInput>input).getResource(), '').then(() => {
......@@ -188,7 +187,8 @@ export class TextFileEditor extends BaseTextEditor {
}
});
});
})
}),
CancelAction
]
}));
}
......
......@@ -129,16 +129,16 @@ export class BaseFileAction extends Action {
protected onErrorWithRetry(error: any, retry: () => TPromise<any>, extraAction?: Action): void {
let actions = [
CancelAction,
new Action(this.id, nls.localize('retry', "Retry"), null, true, () => retry())
new Action(this.id, nls.localize('retry', "Retry"), null, true, () => retry()),
CancelAction
];
if (extraAction) {
actions.push(extraAction);
actions.unshift(extraAction);
}
let errorWithRetry: IMessageWithAction = {
actions: actions,
actions,
message: errors.toErrorMessage(error, false)
};
......
......@@ -70,8 +70,21 @@ export class SaveErrorHandler implements ISaveErrorHandler {
const isReadonly = (<IFileOperationResult>error).fileOperationResult === FileOperationResult.FILE_READ_ONLY;
const actions: Action[] = [];
// Cancel
actions.push(CancelAction);
// Save As
actions.push(new Action('workbench.files.action.saveAs', SaveFileAsAction.LABEL, null, true, () => {
const saveAsAction = this.instantiationService.createInstance(SaveFileAsAction, SaveFileAsAction.ID, SaveFileAsAction.LABEL);
saveAsAction.setResource(resource);
return saveAsAction.run().then(() => { saveAsAction.dispose(); return true; });
}));
// Discard
actions.push(new Action('workbench.files.action.discard', nls.localize('discard', "Discard"), null, true, () => {
const revertFileAction = this.instantiationService.createInstance(RevertFileAction, RevertFileAction.ID, RevertFileAction.LABEL);
revertFileAction.setResource(resource);
return revertFileAction.run().then(() => { revertFileAction.dispose(); return true; });
}));
// Retry
if (isReadonly) {
......@@ -91,21 +104,8 @@ export class SaveErrorHandler implements ISaveErrorHandler {
}));
}
// Discard
actions.push(new Action('workbench.files.action.discard', nls.localize('discard', "Discard"), null, true, () => {
const revertFileAction = this.instantiationService.createInstance(RevertFileAction, RevertFileAction.ID, RevertFileAction.LABEL);
revertFileAction.setResource(resource);
return revertFileAction.run().then(() => { revertFileAction.dispose(); return true; });
}));
// Save As
actions.push(new Action('workbench.files.action.saveAs', SaveFileAsAction.LABEL, null, true, () => {
const saveAsAction = this.instantiationService.createInstance(SaveFileAsAction, SaveFileAsAction.ID, SaveFileAsAction.LABEL);
saveAsAction.setResource(resource);
return saveAsAction.run().then(() => { saveAsAction.dispose(); return true; });
}));
// Cancel
actions.push(CancelAction);
let errorMessage: string;
if (isReadonly) {
......@@ -116,7 +116,7 @@ export class SaveErrorHandler implements ISaveErrorHandler {
message = {
message: errorMessage,
actions: actions
actions
};
}
......
......@@ -479,15 +479,15 @@ export class GitService extends EventEmitter
messageService.show(severity.Warning, {
message: localize('updateGit', "You seem to have git {0} installed. Code works best with git >=2.0.0.", version),
actions: [
CloseAction,
new Action('downloadLatest', localize('download', "Download"), '', true, () => {
shell.openExternal('https://git-scm.com/');
return null;
}),
new Action('neverShowAgain', localize('neverShowAgain', "Don't show again"), null, true, () => {
storageService.store(IgnoreOldGitStorageKey, true, StorageScope.GLOBAL);
return null;
}),
new Action('downloadLatest', localize('download', "Download"), '', true, () => {
shell.openExternal('https://git-scm.com/');
return null;
})
CloseAction
]
});
}
......@@ -792,7 +792,7 @@ export class GitService extends EventEmitter
error = createError(
localize('checkNativeConsole', "There was an issue running a git operation. Please review the output or use a console to check the state of your repository."),
{ actions: [showOutputAction, cancelAction] }
{ actions: [cancelAction, showOutputAction] }
);
(<any>error).gitErrorCode = gitErrorCode;
......
......@@ -85,7 +85,7 @@ class NPSContribution implements IWorkbenchContribution {
return TPromise.as(null);
});
const actions = [takeSurveyAction, remindMeLaterAction, neverAgainAction];
const actions = [neverAgainAction, remindMeLaterAction, takeSurveyAction ];
// TODO@Ben need this setTimeout due to #9769
setTimeout(() => messageService.show(Severity.Info, { message, actions }));
......
......@@ -948,7 +948,7 @@ class TaskService extends EventEmitter implements ITaskService {
? this.getConfigureAction(buildError.code)
: new TerminateAction(TerminateAction.ID, TerminateAction.TEXT, this, this.telemetryService, this.messageService, this.contextService);
closeAction.closeFunction = this.messageService.show(buildError.severity, { message: buildError.message, actions: [closeAction, action ] });
closeAction.closeFunction = this.messageService.show(buildError.severity, { message: buildError.message, actions: [action, closeAction ] });
} else {
this.messageService.show(buildError.severity, buildError.message);
}
......
......@@ -45,8 +45,8 @@ export class UpdateContribution implements IWorkbenchContribution {
messageService.show(Severity.Info, {
message: nls.localize('releaseNotes', "Welcome to {0} v{1}! Would you like to read the Release Notes?", product.nameLong, pkg.version),
actions: [
CloseAction,
ShowReleaseNotesAction(product.releaseNotesUrl, true)
ShowReleaseNotesAction(product.releaseNotesUrl, true),
CloseAction
]
});
}, 0);
......@@ -58,8 +58,8 @@ export class UpdateContribution implements IWorkbenchContribution {
messageService.show(Severity.Info, {
message: nls.localize('licenseChanged', "Our license terms have changed, please go through them.", product.nameLong, pkg.version),
actions: [
CloseAction,
LinkAction('update.showLicense', nls.localize('license', "Read License"), product.licenseUrl)
LinkAction('update.showLicense', nls.localize('license', "Read License"), product.licenseUrl),
CloseAction
]
});
}, 0);
......@@ -73,16 +73,16 @@ export class UpdateContribution implements IWorkbenchContribution {
messageService.show(Severity.Info, {
message: nls.localize('insiderBuilds', "Insider builds are becoming daily builds!", product.nameLong, pkg.version),
actions: [
CloseAction,
new Action('update.neverAgain', nls.localize('neverShowAgain', "Never Show Again"), '', true, () => {
new Action('update.insiderBuilds', nls.localize('readmore', "Read More"), '', true, () => {
shell.openExternal('http://go.microsoft.com/fwlink/?LinkID=798816');
storageService.store(UpdateContribution.INSIDER_KEY, false, StorageScope.GLOBAL);
return TPromise.as(null);
}),
new Action('update.insiderBuilds', nls.localize('readmore', "Read More"), '', true, () => {
shell.openExternal('http://go.microsoft.com/fwlink/?LinkID=798816');
new Action('update.neverAgain', nls.localize('neverShowAgain', "Never Show Again"), '', true, () => {
storageService.store(UpdateContribution.INSIDER_KEY, false, StorageScope.GLOBAL);
return TPromise.as(null);
})
}),
CloseAction,
]
});
}, 0);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册