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

navbar in extension editor

上级 ecf2e326
...@@ -9,6 +9,8 @@ import 'vs/css!./media/extensionEditor'; ...@@ -9,6 +9,8 @@ import 'vs/css!./media/extensionEditor';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base'; import { TPromise } from 'vs/base/common/winjs.base';
import { marked } from 'vs/base/common/marked/marked'; import { marked } from 'vs/base/common/marked/marked';
import Event, { Emitter } from 'vs/base/common/event';
import { Action } from 'vs/base/common/actions';
import { onUnexpectedError } from 'vs/base/common/errors'; import { onUnexpectedError } from 'vs/base/common/errors';
import { IDisposable, empty, dispose, toDisposable } from 'vs/base/common/lifecycle'; import { IDisposable, empty, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { Builder } from 'vs/base/browser/builder'; import { Builder } from 'vs/base/browser/builder';
...@@ -21,7 +23,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti ...@@ -21,7 +23,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IThemeService } from 'vs/workbench/services/themes/common/themeService'; import { IThemeService } from 'vs/workbench/services/themes/common/themeService';
import { ExtensionsInput } from './extensionsInput'; import { ExtensionsInput } from './extensionsInput';
import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID } from './extensions'; import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, IExtension } from './extensions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ITemplateData } from './extensionsList'; import { ITemplateData } from './extensionsList';
import { RatingsWidget, InstallWidget } from './extensionsWidgets'; import { RatingsWidget, InstallWidget } from './extensionsWidgets';
...@@ -44,6 +46,52 @@ function renderBody(body: string): string { ...@@ -44,6 +46,52 @@ function renderBody(body: string): string {
</html>`; </html>`;
} }
class NavBar {
private _onChange = new Emitter<string>();
get onChange(): Event<string> { return this._onChange.event; }
private actions: Action[];
private actionbar: ActionBar;
constructor(container: HTMLElement) {
const element = append(container, $('.navbar'));
this.actions = [];
this.actionbar = new ActionBar(element, { animated: false });
}
push(id: string, label: string): void {
const run = () => {
this._onChange.fire(id);
this.actions.forEach(a => a.enabled = a.id !== action.id);
return TPromise.as(null);
};
const action = new Action(id, label, null, true, run);
this.actions.push(action);
this.actionbar.push(action);
if (this.actions.length === 1) {
run();
}
}
clear(): void {
this.actions = dispose(this.actions);
this.actionbar.clear();
}
dispose(): void {
this.actionbar = dispose(this.actionbar);
}
}
const NavbarSection = {
Readme: 'readme',
Configuration: 'configuration'
};
export class ExtensionEditor extends BaseEditor { export class ExtensionEditor extends BaseEditor {
static ID: string = 'workbench.editor.extension'; static ID: string = 'workbench.editor.extension';
...@@ -55,13 +103,15 @@ export class ExtensionEditor extends BaseEditor { ...@@ -55,13 +103,15 @@ export class ExtensionEditor extends BaseEditor {
private installCount: HTMLElement; private installCount: HTMLElement;
private rating: HTMLAnchorElement; private rating: HTMLAnchorElement;
private description: HTMLElement; private description: HTMLElement;
private actionBar: ActionBar; private extensionActionBar: ActionBar;
private body: HTMLElement; private navbar: NavBar;
private content: HTMLElement;
private _highlight: ITemplateData; private _highlight: ITemplateData;
private highlightDisposable: IDisposable; private highlightDisposable: IDisposable;
private transientDisposables: IDisposable[]; private contentDisposables: IDisposable[] = [];
private transientDisposables: IDisposable[] = [];
private disposables: IDisposable[]; private disposables: IDisposable[];
constructor( constructor(
...@@ -111,11 +161,14 @@ export class ExtensionEditor extends BaseEditor { ...@@ -111,11 +161,14 @@ export class ExtensionEditor extends BaseEditor {
this.description = append(details, $('.description')); this.description = append(details, $('.description'));
const actions = append(details, $('.actions')); const extensionActions = append(details, $('.actions'));
this.actionBar = new ActionBar(actions, { animated: false }); this.extensionActionBar = new ActionBar(extensionActions, { animated: false });
this.disposables.push(this.actionBar); this.disposables.push(this.extensionActionBar);
const body = append(root, $('.body'));
this.navbar = new NavBar(body);
this.body = append(root, $('.body')); this.content = append(body, $('.content'));
} }
setInput(input: ExtensionsInput, options: EditorOptions): TPromise<void> { setInput(input: ExtensionsInput, options: EditorOptions): TPromise<void> {
...@@ -163,42 +216,64 @@ export class ExtensionEditor extends BaseEditor { ...@@ -163,42 +216,64 @@ export class ExtensionEditor extends BaseEditor {
updateAction.extension = extension; updateAction.extension = extension;
enableAction.extension = extension; enableAction.extension = extension;
this.actionBar.clear(); this.extensionActionBar.clear();
this.actionBar.push([enableAction, updateAction, installAction], { icon: true, label: true }); this.extensionActionBar.push([enableAction, updateAction, installAction], { icon: true, label: true });
this.transientDisposables.push(enableAction, updateAction, installAction); this.transientDisposables.push(enableAction, updateAction, installAction);
this.body.innerHTML = ''; this.navbar.clear();
let promise: TPromise<any> = super.setInput(input, options); this.navbar.onChange(this.onNavbarChange.bind(this, extension), this, this.transientDisposables);
if (extension.readmeUrl) { this.navbar.push(NavbarSection.Readme, localize('readme', "Readme"));
promise = promise // this.navbar.push(NavbarSection.Configuration, localize('configuration', "Config"));
.then(() => addClass(this.body, 'loading'))
.then(() => this.extensionsWorkbenchService.getReadmeContents(extension)) this.content.innerHTML = '';
.then(marked.parse)
.then<void>(body => { return super.setInput(input, options);
const webview = new WebView( }
this.body,
document.querySelector('.monaco-editor-background') private onNavbarChange(extension: IExtension, id: string): void {
); this.contentDisposables = dispose(this.contentDisposables);
this.content.innerHTML = '';
webview.style(this.themeService.getColorTheme());
webview.contents = [renderBody(body)]; switch (id) {
case NavbarSection.Readme: return this.openReadme(extension);
const linkListener = webview.onDidClickLink(link => shell.openExternal(link.toString())); case NavbarSection.Configuration: return this.openConfiguration(extension);
const themeListener = this.themeService.onDidColorThemeChange(themeId => webview.style(themeId));
this.transientDisposables.push(webview, linkListener, themeListener);
})
.then(null, () => null)
.then(() => removeClass(this.body, 'loading'));
} else {
promise = promise
.then(() => append(this.body, $('p')))
.then(p => p.textContent = localize('noReadme', "No README available."));
} }
}
this.transientDisposables.push(toDisposable(() => promise.cancel())); private openReadme(extension: IExtension) {
if (!extension.readmeUrl) {
const p = append(this.content, $('p'));
p.textContent = localize('noReadme', "No README available.");
return;
}
addClass(this.content, 'loading');
const promise = this.extensionsWorkbenchService.getReadmeContents(extension)
.then(marked.parse)
.then<void>(body => {
const webview = new WebView(
this.content,
document.querySelector('.monaco-editor-background')
);
webview.style(this.themeService.getColorTheme());
webview.contents = [renderBody(body)];
const linkListener = webview.onDidClickLink(link => shell.openExternal(link.toString()));
const themeListener = this.themeService.onDidColorThemeChange(themeId => webview.style(themeId));
this.contentDisposables.push(webview, linkListener, themeListener);
})
.then(null, () => null)
.then(() => removeClass(this.content, 'loading'));
this.contentDisposables.push(toDisposable(() => promise.cancel()));
}
return TPromise.as(null); private openConfiguration(extension: IExtension) {
this.content.innerHTML = '';
this.content.innerText = 'configuration';
} }
layout(): void { layout(): void {
......
...@@ -101,6 +101,39 @@ ...@@ -101,6 +101,39 @@
overflow: hidden; overflow: hidden;
} }
.extension-editor > .body > p { .extension-editor > .body > .navbar {
margin: 20px; height: 36px;
text-transform: uppercase;
font-size: 14px;
line-height: 36px;
padding-left: 20px;
border-bottom: 1px solid rgba(136, 136, 136, 0.45);
box-sizing: border-box;
}
.extension-editor > .body > .navbar > .monaco-action-bar > .actions-container {
justify-content: initial;
}
.extension-editor > .body > .navbar > .monaco-action-bar > .actions-container > .action-item > .action-label {
margin-right: 16px;
}
.extension-editor > .body > .navbar > .monaco-action-bar > .actions-container > .action-item > .action-label {
font-size: inherit;
}
.extension-editor > .body > .navbar > .monaco-action-bar > .actions-container > .action-item.disabled > .action-label {
opacity: 1;
text-decoration: underline;
font-weight: bold;
}
.extension-editor > .body > .navbar > .monaco-action-bar > .actions-container > .action-item > .action-label:hover {
text-decoration: underline;
}
.extension-editor > .body > .content {
height: calc(100% - 36px);
overflow: hidden;
} }
\ No newline at end of file
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
.quick-open-widget .extension.loading, .quick-open-widget .extension.loading,
.extensions-viewlet > .extensions .extension.loading, .extensions-viewlet > .extensions .extension.loading,
.extension-editor > .body.loading { .extension-editor > .body > .content.loading {
background: url('data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjU3NSIgaGVpZ2h0PSI2cHgiPg0KICA8c3R5bGU+DQogICAgY2lyY2xlIHsNCiAgICAgIGFuaW1hdGlvbjogYmFsbCAyLjVzIGN1YmljLWJlemllcigwLjAwMCwgMS4wMDAsIDEuMDAwLCAwLjAwMCkgaW5maW5pdGU7DQogICAgICBmaWxsOiAjYmJiOw0KICAgIH0NCg0KICAgICNiYWxscyB7DQogICAgICBhbmltYXRpb246IGJhbGxzIDIuNXMgbGluZWFyIGluZmluaXRlOw0KICAgIH0NCg0KICAgICNjaXJjbGUyIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjFzOyB9DQogICAgI2NpcmNsZTMgeyBhbmltYXRpb24tZGVsYXk6IDAuMnM7IH0NCiAgICAjY2lyY2xlNCB7IGFuaW1hdGlvbi1kZWxheTogMC4zczsgfQ0KICAgICNjaXJjbGU1IHsgYW5pbWF0aW9uLWRlbGF5OiAwLjRzOyB9DQoNCiAgICBAa2V5ZnJhbWVzIGJhbGwgew0KICAgICAgZnJvbSB7IHRyYW5zZm9ybTogbm9uZTsgfQ0KICAgICAgMjAlIHsgdHJhbnNmb3JtOiBub25lOyB9DQogICAgICA4MCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoODY0cHgpOyB9DQogICAgICB0byB7IHRyYW5zZm9ybTogdHJhbnNsYXRlWCg4NjRweCk7IH0NCiAgICB9DQoNCiAgICBAa2V5ZnJhbWVzIGJhbGxzIHsNCiAgICAgIGZyb20geyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTQwcHgpOyB9DQogICAgICB0byB7IHRyYW5zZm9ybTogdHJhbnNsYXRlWCgzMHB4KTsgfQ0KICAgIH0NCiAgPC9zdHlsZT4NCiAgPGcgaWQ9ImJhbGxzIj4NCiAgICA8Y2lyY2xlIGNsYXNzPSJjaXJjbGUiIGlkPSJjaXJjbGUxIiBjeD0iLTExNSIgY3k9IjMiIHI9IjMiLz4NCiAgICA8Y2lyY2xlIGNsYXNzPSJjaXJjbGUiIGlkPSJjaXJjbGUyIiBjeD0iLTEzMCIgY3k9IjMiIHI9IjMiIC8+DQogICAgPGNpcmNsZSBjbGFzcz0iY2lyY2xlIiBpZD0iY2lyY2xlMyIgY3g9Ii0xNDUiIGN5PSIzIiByPSIzIiAvPg0KICAgIDxjaXJjbGUgY2xhc3M9ImNpcmNsZSIgaWQ9ImNpcmNsZTQiIGN4PSItMTYwIiBjeT0iMyIgcj0iMyIgLz4NCiAgICA8Y2lyY2xlIGNsYXNzPSJjaXJjbGUiIGlkPSJjaXJjbGU1IiBjeD0iLTE3NSIgY3k9IjMiIHI9IjMiIC8+DQogIDwvZz4NCjwvc3ZnPg==') center center no-repeat; background: url('data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjU3NSIgaGVpZ2h0PSI2cHgiPg0KICA8c3R5bGU+DQogICAgY2lyY2xlIHsNCiAgICAgIGFuaW1hdGlvbjogYmFsbCAyLjVzIGN1YmljLWJlemllcigwLjAwMCwgMS4wMDAsIDEuMDAwLCAwLjAwMCkgaW5maW5pdGU7DQogICAgICBmaWxsOiAjYmJiOw0KICAgIH0NCg0KICAgICNiYWxscyB7DQogICAgICBhbmltYXRpb246IGJhbGxzIDIuNXMgbGluZWFyIGluZmluaXRlOw0KICAgIH0NCg0KICAgICNjaXJjbGUyIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjFzOyB9DQogICAgI2NpcmNsZTMgeyBhbmltYXRpb24tZGVsYXk6IDAuMnM7IH0NCiAgICAjY2lyY2xlNCB7IGFuaW1hdGlvbi1kZWxheTogMC4zczsgfQ0KICAgICNjaXJjbGU1IHsgYW5pbWF0aW9uLWRlbGF5OiAwLjRzOyB9DQoNCiAgICBAa2V5ZnJhbWVzIGJhbGwgew0KICAgICAgZnJvbSB7IHRyYW5zZm9ybTogbm9uZTsgfQ0KICAgICAgMjAlIHsgdHJhbnNmb3JtOiBub25lOyB9DQogICAgICA4MCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoODY0cHgpOyB9DQogICAgICB0byB7IHRyYW5zZm9ybTogdHJhbnNsYXRlWCg4NjRweCk7IH0NCiAgICB9DQoNCiAgICBAa2V5ZnJhbWVzIGJhbGxzIHsNCiAgICAgIGZyb20geyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTQwcHgpOyB9DQogICAgICB0byB7IHRyYW5zZm9ybTogdHJhbnNsYXRlWCgzMHB4KTsgfQ0KICAgIH0NCiAgPC9zdHlsZT4NCiAgPGcgaWQ9ImJhbGxzIj4NCiAgICA8Y2lyY2xlIGNsYXNzPSJjaXJjbGUiIGlkPSJjaXJjbGUxIiBjeD0iLTExNSIgY3k9IjMiIHI9IjMiLz4NCiAgICA8Y2lyY2xlIGNsYXNzPSJjaXJjbGUiIGlkPSJjaXJjbGUyIiBjeD0iLTEzMCIgY3k9IjMiIHI9IjMiIC8+DQogICAgPGNpcmNsZSBjbGFzcz0iY2lyY2xlIiBpZD0iY2lyY2xlMyIgY3g9Ii0xNDUiIGN5PSIzIiByPSIzIiAvPg0KICAgIDxjaXJjbGUgY2xhc3M9ImNpcmNsZSIgaWQ9ImNpcmNsZTQiIGN4PSItMTYwIiBjeT0iMyIgcj0iMyIgLz4NCiAgICA8Y2lyY2xlIGNsYXNzPSJjaXJjbGUiIGlkPSJjaXJjbGU1IiBjeD0iLTE3NSIgY3k9IjMiIHI9IjMiIC8+DQogIDwvZz4NCjwvc3ZnPg==') center center no-repeat;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册