Skip to content

Commit

Permalink
extensions styling improvements
Browse files Browse the repository at this point in the history
Signed-off-by: Kenneth Marut <kenneth.marut@ericsson.com>
  • Loading branch information
kenneth-marut-work committed Jul 1, 2020
1 parent 64244a5 commit d5c3701
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 22 deletions.
34 changes: 31 additions & 3 deletions packages/vsx-registry/src/browser/style/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -137,18 +137,46 @@
overflow: hidden;
display: flex;
flex-direction: column;
padding: var(--theia-ui-padding);
padding-top: 0;
position: relative;
}

.theia-vsx-extension-editor .header {
display: flex;
padding: calc(var(--theia-ui-padding)*3) calc(var(--theia-ui-padding)*3) calc(var(--theia-ui-padding)*2);
overflow: hidden;
padding: calc(var(--theia-ui-padding) * 3) calc(var(--theia-ui-padding) * 3) calc(var(--theia-ui-padding) * 3);
flex-shrink: 0;
border-bottom: 1px solid hsla(0, 0% ,50% ,.5);
position: sticky;
top: 0;
width: 100%;
background: var(--theia-editor-background);
}

.theia-vsx-extension-editor .scroll-container {
position: absolute;
bottom: 0;
padding-top: 0;
max-width: 100%;
}

.theia-vsx-extension-editor .body {
flex: 1;
padding: calc(var(--theia-ui-padding)*2);
padding-top: 0;
}

.theia-vsx-extension-editor .body h2:first-of-type {
padding-bottom: var(--theia-ui-padding);
border-bottom: 1px solid hsla(0, 0%, 50%, .5);
margin-top: calc(var(--theia-ui-padding) * 5);
}

.theia-vsx-extension-editor .scroll-container .body pre {
white-space: normal;
}

.theia-vsx-extension-editor .body img {
max-width: 100%;
}

.theia-vsx-extension-editor .header .icon-container {
Expand Down
31 changes: 25 additions & 6 deletions packages/vsx-registry/src/browser/vsx-extension-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import * as React from 'react';
import { inject, injectable, postConstruct } from 'inversify';
import { ReactWidget, Message } from '@theia/core/lib/browser';
import { ReactWidget, Message, Widget } from '@theia/core/lib/browser';
import { VSXExtension } from './vsx-extension';
import { VSXExtensionsModel } from './vsx-extensions-model';

Expand All @@ -32,26 +32,37 @@ export class VSXExtensionEditor extends ReactWidget {
protected readonly model: VSXExtensionsModel;

@postConstruct()
protected init(): void {
protected async init(): Promise<void> {
this.addClass('theia-vsx-extension-editor');
this.id = VSXExtensionEditor.ID + ':' + this.extension.id;
this.title.closable = true;
this.updateTitle();
this.title.iconClass = 'fa fa-puzzle-piece';
this.node.tabIndex = -1;

this.update();
this.toDispose.push(this.model.onDidChange(() => this.update()));
this.extension.resetExtension();
this.update();
}

async getScrollContainer(): Promise<HTMLElement> {
return this.extension.deferredScrollContainer.promise;
}

protected onActivateRequest(msg: Message): void {
super.onActivateRequest(msg);
this.extension.setContainerHeights();
this.node.focus();
super.onActivateRequest(msg);
}

protected onUpdateRequest(msg: Message): void {
super.onUpdateRequest(msg);
this.updateTitle();
this.extension.setContainerHeights();
super.onUpdateRequest(msg);
}

protected onAfterShow(msg: Message): void {
super.onAfterShow(msg);
this.update();
}

protected updateTitle(): void {
Expand All @@ -60,6 +71,14 @@ export class VSXExtensionEditor extends ReactWidget {
this.title.caption = label;
}

protected onResize = async (msg: Widget.ResizeMessage): Promise<void> => {
super.onResize(msg);
if (this.extension) {
this.extension.updateOnResize(msg);
this.update();
}
};

protected render(): React.ReactNode {
return this.extension.renderEditor();
}
Expand Down
128 changes: 115 additions & 13 deletions packages/vsx-registry/src/browser/vsx-extension.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ import { Endpoint } from '@theia/core/lib/browser/endpoint';
import { VSXEnvironment } from '../common/vsx-environment';
import { VSXExtensionsSearchModel } from './vsx-extensions-search-model';
import { VSXExtensionNamespaceAccess, VSXUser } from '../common/vsx-registry-types';
import { Deferred } from '@theia/core/lib/common/promise-util';
import { Widget } from '@theia/core/lib/browser';

const BODY_CONTENT_MAX_WIDTH = 1000;

@injectable()
export class VSXExtensionData {
Expand Down Expand Up @@ -100,6 +104,56 @@ export class VSXExtension implements VSXExtensionData, TreeElement {

protected readonly data: Partial<VSXExtensionData> = {};

protected _body: HTMLDivElement | undefined;
get body(): HTMLDivElement | undefined {
return this._body;
}
setBody = (element: HTMLDivElement | undefined) => {
this._body = element;
this._bodyStyles = { ...this._bodyStyles, visibility: 'unset' };
};

protected _scrollContainer: HTMLDivElement | undefined;
get scrollContainer(): HTMLDivElement | undefined {
return this._scrollContainer;
}
setScrollContainer = (element: HTMLDivElement | undefined) => {
if (element) {
this._scrollContainer = element;
this._deferredScrollContainer.resolve(element);
}
};

protected _header: HTMLDivElement | undefined;
get header(): HTMLDivElement | undefined {
return this._header;
}
setHeader = (element: HTMLDivElement | undefined) => {
this._header = element;
};

protected _bodyStyles: React.CSSProperties = {};
get bodyStyles(): React.CSSProperties {
return this._bodyStyles;
}

protected _scrollContainerStyles: React.CSSProperties = {};
get scrollContainerStyles(): React.CSSProperties {
return this._scrollContainerStyles;
}

protected _deferredScrollContainer: Deferred<HTMLDivElement>;
get deferredScrollContainer(): Deferred<HTMLDivElement> {
return this._deferredScrollContainer;
}

resetExtension(): void {
// Reset deferred scroll container vsx-extension-editor is closed and reopened
this._deferredScrollContainer = new Deferred<HTMLDivElement>();
// hide body during first render to avoid flickering while scroll container height is being calculated
this._bodyStyles = { visibility: 'hidden' };
}

get uri(): URI {
return VSXExtensionUri.toUri(this.id);
}
Expand Down Expand Up @@ -134,6 +188,33 @@ export class VSXExtension implements VSXExtensionData, TreeElement {
}
}

updateOnResize(msg: Widget.ResizeMessage): void {
const scrollStyles: React.CSSProperties = { ...this.scrollContainerStyles };
const bodyStyles: React.CSSProperties = { ...this.bodyStyles };
if (this.body && this.scrollContainer) {
scrollStyles.width = `${msg.width}px`;
if (msg.width > BODY_CONTENT_MAX_WIDTH) {
const sideMargin = (msg.width - BODY_CONTENT_MAX_WIDTH) / 2;
bodyStyles.marginLeft = `${sideMargin}px`;
bodyStyles.marginRight = `${sideMargin}px`;
} else if (msg.width <= BODY_CONTENT_MAX_WIDTH) {
bodyStyles.marginLeft = '0px';
bodyStyles.marginRight = '0px';
}
this._scrollContainerStyles = scrollStyles;
this._bodyStyles = bodyStyles;
}
}

setContainerHeights = (): void => {
const scrollStyles = { ...this.scrollContainerStyles };
if (this.scrollContainer && this.header) {
const headerHeight = this.header.clientHeight;
scrollStyles.height = `calc(100% - (${headerHeight}px + 1px))`;
this._scrollContainerStyles = scrollStyles;
}
};

protected getData<K extends keyof VSXExtensionData>(key: K): VSXExtensionData[K] {
const plugin = this.plugin;
const model = plugin && plugin.metadata.model;
Expand Down Expand Up @@ -268,7 +349,6 @@ export class VSXExtension implements VSXExtensionData, TreeElement {
renderEditor(): React.ReactNode {
return <VSXExtensionEditorComponent extension={this} />;
}

}

export abstract class AbstractVSXExtensionComponent extends React.Component<AbstractVSXExtensionComponent.Props> {
Expand Down Expand Up @@ -351,13 +431,28 @@ export class VSXExtensionComponent extends AbstractVSXExtensionComponent {
}

export class VSXExtensionEditorComponent extends AbstractVSXExtensionComponent {

protected scrollContainer?: HTMLDivElement;
protected header?: HTMLDivElement;
protected body?: HTMLDivElement;

componentDidMount(): void {
if (this.scrollContainer && this.header && this.body) {
this.props.extension.setHeader(this.header);
this.props.extension.setBody(this.body);
this.props.extension.setScrollContainer(this.scrollContainer);
this.props.extension.setContainerHeights();
}
}

render(): React.ReactNode {
const {
builtin, preview, id, iconUrl, publisher, displayName, description,
averageRating, downloadCount, repository, license, readme, version
builtin, preview, id, iconUrl, publisher, displayName, description, version,
averageRating, downloadCount, repository, license, readme,
bodyStyles, scrollContainerStyles
} = this.props.extension;
return <React.Fragment>
<div className='header'>
<div className='header' ref={ref => this.header = ref || undefined}>
{iconUrl ?
<img className='icon-container' src={iconUrl} /> :
<div className='icon-container placeholder' />}
Expand All @@ -384,11 +479,20 @@ export class VSXExtensionEditorComponent extends AbstractVSXExtensionComponent {
{this.renderAction()}
</div>
</div>
{readme && <div className='body'
ref={body => this.body = (body || undefined)}
onClick={this.openLink}
dangerouslySetInnerHTML={{ __html: readme }} />}
</React.Fragment>;
{
readme &&
< div className='scroll-container'
style={scrollContainerStyles}
ref={ref => this.scrollContainer = ref || undefined}>
{<div className='body'
ref={ref => this.body = ref || undefined}
onClick={this.openLink}
style={bodyStyles}
dangerouslySetInnerHTML={{ __html: readme }}
/>}
</div>
}
</React.Fragment >;
}

protected renderNamespaceAccess(): React.ReactNode {
Expand Down Expand Up @@ -421,11 +525,9 @@ export class VSXExtensionEditorComponent extends AbstractVSXExtensionComponent {
</React.Fragment>;
}

protected body: HTMLElement | undefined;

// TODO replace with webview
readonly openLink = (event: React.MouseEvent) => {
if (!this.body) {
if (!this.props.extension.body) {
return;
}
const target = event.nativeEvent.target;
Expand All @@ -434,7 +536,7 @@ export class VSXExtensionEditorComponent extends AbstractVSXExtensionComponent {
}
let node = target;
while (node.tagName.toLowerCase() !== 'a') {
if (node === this.body) {
if (node === this.props.extension.body) {
return;
}
if (!(node.parentElement instanceof HTMLElement)) {
Expand Down
1 change: 1 addition & 0 deletions packages/vsx-registry/src/browser/vsx-extensions-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export class VSXExtensionsModel {
readonly search: VSXExtensionsSearchModel;

protected readonly initialized = new Deferred<void>();
// protected _onResize(msg: Message): void;

@postConstruct()
protected async init(): Promise<void> {
Expand Down

0 comments on commit d5c3701

Please sign in to comment.