提交 e41c6198 编写于 作者: J Joao Moreno

extension status bar: errors should only display once

上级 f4ca1865
......@@ -13,6 +13,7 @@ import strings = require('vs/base/common/strings');
import {IAction} from 'vs/base/common/actions';
import {IXHRResponse} from 'vs/base/common/http';
import Severity from 'vs/base/common/severity';
import { TPromise } from 'vs/base/common/winjs.base';
export interface ErrorListenerCallback {
(error: any): void;
......@@ -88,6 +89,10 @@ export function onUnexpectedError(e: any): void {
}
}
export function onUnexpectedPromiseError<T>(promise: TPromise<T>): TPromise<T> {
return promise.then<T>(null, onUnexpectedError);
}
export interface IConnectionErrorData {
status: number;
statusText?: string;
......
......@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./extensions';
import platform = require('vs/platform/platform');
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import statusbar = require('vs/workbench/browser/parts/statusbar/statusbar');
......
......@@ -135,23 +135,26 @@
/* Status bar */
.monaco-shell .extensions-statusbar {
padding: 0 5px 0 25px;
line-height: 22px;
background: url('extensions-status.svg') center center no-repeat;
background-size: 14px;
background-position: 4px 50%;
padding: 0 4px;
}
.monaco-shell .extensions-suggestions {
padding: 0 5px 0 5px;
-webkit-transition: visibility 250ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
transition: visibility 250ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
.monaco-shell .extensions-statusbar span:not(:first-child) {
padding-left: 4px;
}
.monaco-shell .extensions-suggestions > .octicon {
.monaco-shell .extensions-statusbar > .octicon {
position: relative;
font-size: 14px;
}
.monaco-shell .extensions-suggestions.disabled {
display: none;
}
\ No newline at end of file
.monaco-shell .extensions-statusbar.has-errors > .octicon::after {
content: '';
width: 6px;
height: 6px;
background-color: #CC6633;
position: absolute;
top: 0;
right: 0;
border-radius: 10px;
border: 1px solid white;
}
......@@ -3,8 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/extensions';
import nls = require('vs/nls');
import { IDisposable, disposeAll } from 'vs/base/common/lifecycle';
import { TPromise } from 'vs/base/common/winjs.base';
......
......@@ -5,80 +5,92 @@
import nls = require('vs/nls');
import Severity from 'vs/base/common/severity';
import dom = require('vs/base/browser/dom');
import { emmet as $, append, toggleClass } from 'vs/base/browser/dom';
import lifecycle = require('vs/base/common/lifecycle');
import {onUnexpectedError} from 'vs/base/common/errors';
import { onUnexpectedPromiseError as _ } from 'vs/base/common/errors';
import { assign } from 'vs/base/common/objects';
import { Action } from 'vs/base/common/actions';
import statusbar = require('vs/workbench/browser/parts/statusbar/statusbar');
import { IExtensionService, IExtensionsStatus } from 'vs/platform/extensions/common/extensions';
import { IExtensionService, IMessage } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IMessageService, CloseAction } from 'vs/platform/message/common/message';
import { UninstallAction } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions';
import { IExtensionsService } from 'vs/workbench/parts/extensions/common/extensions';
var $ = dom.emmet;
interface IState {
errors: IMessage[];
}
export class ExtensionsStatusbarItem implements statusbar.IStatusbarItem {
private toDispose: lifecycle.IDisposable[];
private domNode: HTMLElement;
private status: { [id: string]: IExtensionsStatus };
private container: HTMLElement;
private messageCount: number;
private state: IState = { errors: [] };
constructor(
@IExtensionService extensionService: IExtensionService,
@IExtensionService private extensionService: IExtensionService,
@IMessageService private messageService: IMessageService,
@IExtensionsService protected extensionsService: IExtensionsService,
@IInstantiationService protected instantiationService: IInstantiationService
) {}
) {
this.toDispose = [];
this.messageCount = 0;
render(container: HTMLElement): lifecycle.IDisposable {
this.domNode = append(container, $('a.extensions-statusbar'));
this.domNode.onclick = () => this.onClick();
extensionService.onReady().then(() => {
this.status = extensionService.getExtensionsStatus();
Object.keys(this.status).forEach(key => {
this.messageCount += this.status[key].messages.filter(message => message.type > Severity.Info).length;
});
this.render(this.container);
append(this.domNode, $('span.octicon.octicon-package'));
_(this.extensionService.onReady()).done(() => {
const status = this.extensionService.getExtensionsStatus();
const errors = Object.keys(status)
.map(k => status[k].messages)
.reduce((r, m) => r.concat(m), [])
.filter(m => m.type > Severity.Info);
this.updateState({ errors });
});
return null;
}
public render(container: HTMLElement): lifecycle.IDisposable {
this.container = container;
if (this.messageCount > 0) {
this.domNode = dom.append(container, $('a.extensions-statusbar'));
const issueLabel = this.messageCount > 1 ? nls.localize('issues', "issues") : nls.localize('issue', "issue");
private updateState(obj: any): void {
this.state = assign(this.state, obj);
this.onStateChange();
}
private onStateChange(): void {
toggleClass(this.domNode, 'has-errors', this.state.errors.length > 0);
if (this.state.errors.length > 0) {
const issueLabel = this.state.errors.length > 1 ? nls.localize('issues', "issues") : nls.localize('issue', "issue");
const extensionLabel = nls.localize('extension', "extension");
this.domNode.title = `${ this.messageCount } ${ extensionLabel } ${ issueLabel }`;
this.domNode.textContent = `${ this.messageCount } ${ issueLabel }`;
this.toDispose.push(dom.addDisposableListener(this.domNode, 'click', () => {
this.extensionsService.getInstalled().done(installed => {
Object.keys(this.status).forEach(key => {
this.status[key].messages.forEach(m => {
if (m.type > Severity.Info) {
const extension = installed.filter(ext => ext.path === m.source).pop();
const actions = [CloseAction];
const name = (extension && extension.name) || m.source;
const message = `${ name }: ${ m.message }`;
if (extension) {
const actionLabel = nls.localize('uninstall', "Uninstall");
actions.push(new Action('extensions.uninstall2', actionLabel, null, true, () => this.instantiationService.createInstance(UninstallAction).run(extension)));
}
this.messageService.show(m.type, { message, actions });
}
});
});
}, onUnexpectedError);
}));
this.domNode.title = `${ this.state.errors.length } ${ extensionLabel } ${ issueLabel }`;
} else {
this.domNode.title = nls.localize('extensions', "Extensions");
}
}
return {
dispose: () => lifecycle.disposeAll(this.toDispose)
};
private onClick(): void {
if (this.state.errors.length > 0) {
this.showErrors(this.state.errors);
this.updateState({ errors: [] });
}
}
private showErrors(errors: IMessage[]): void {
_(this.extensionsService.getInstalled()).done(installed => {
errors.forEach(m => {
const extension = installed.filter(ext => ext.path === m.source).pop();
const actions = [CloseAction];
const name = (extension && extension.name) || m.source;
const message = `${ name }: ${ m.message }`;
if (extension) {
const actionLabel = nls.localize('uninstall', "Uninstall");
actions.push(new Action('extensions.uninstall2', actionLabel, null, true, () => this.instantiationService.createInstance(UninstallAction).run(extension)));
}
this.messageService.show(m.type, { message, actions });
});
});
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 60 60" style="enable-background:new 0 0 60 60;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<g id="iconBg">
<path class="st0" d="M12.9,47.1H30V60H0V0h25.7v12.9H12.9V47.1z M17.1,42.9h25.7V17.1H17.1V42.9z M30,0v12.9h8.6V8.6h12.9v12.9
h-4.3V30H60V0H30z M47.1,47.1H34.3V60H60V34.3H47.1V47.1z"/>
</g>
</svg>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册