This commit is contained in:
Sandeep Somavarapu
2025-12-18 18:04:33 +01:00
committed by GitHub
parent 09bd247b49
commit 643cd83bc6
2 changed files with 97 additions and 75 deletions

View File

@@ -664,12 +664,24 @@ export class ExtensionEditor extends EditorPane {
} }
private open(id: string, extension: IExtension, template: IExtensionEditorTemplate, token: CancellationToken): Promise<IActiveElement | null> { private open(id: string, extension: IExtension, template: IExtensionEditorTemplate, token: CancellationToken): Promise<IActiveElement | null> {
// Setup common container structure for all tabs
const details = append(template.content, $('.details'));
const contentContainer = append(details, $('.content-container'));
const additionalDetailsContainer = append(details, $('.additional-details-container'));
const layout = () => details.classList.toggle('narrow', this.dimension && this.dimension.width < 500);
layout();
this.contentDisposables.add(toDisposable(arrays.insert(this.layoutParticipants, { layout })));
// Render additional details synchronously to avoid flicker
this.renderAdditionalDetails(additionalDetailsContainer, extension);
switch (id) { switch (id) {
case ExtensionEditorTab.Readme: return this.openDetails(extension, template, token); case ExtensionEditorTab.Readme: return this.openDetails(extension, contentContainer, token);
case ExtensionEditorTab.Features: return this.openFeatures(template, token); case ExtensionEditorTab.Features: return this.openFeatures(extension, contentContainer, token);
case ExtensionEditorTab.Changelog: return this.openChangelog(extension, template, token); case ExtensionEditorTab.Changelog: return this.openChangelog(extension, contentContainer, token);
case ExtensionEditorTab.Dependencies: return this.openExtensionDependencies(extension, template, token); case ExtensionEditorTab.Dependencies: return this.openExtensionDependencies(extension, contentContainer, token);
case ExtensionEditorTab.ExtensionPack: return this.openExtensionPack(extension, template, token); case ExtensionEditorTab.ExtensionPack: return this.openExtensionPack(extension, contentContainer, token);
} }
return Promise.resolve(null); return Promise.resolve(null);
} }
@@ -835,24 +847,15 @@ export class ExtensionEditor extends EditorPane {
</html>`; </html>`;
} }
private async openDetails(extension: IExtension, template: IExtensionEditorTemplate, token: CancellationToken): Promise<IActiveElement | null> { private async openDetails(extension: IExtension, contentContainer: HTMLElement, token: CancellationToken): Promise<IActiveElement | null> {
const details = append(template.content, $('.details'));
const readmeContainer = append(details, $('.readme-container'));
const additionalDetailsContainer = append(details, $('.additional-details-container'));
const layout = () => details.classList.toggle('narrow', this.dimension && this.dimension.width < 500);
layout();
this.contentDisposables.add(toDisposable(arrays.insert(this.layoutParticipants, { layout })));
let activeElement: IActiveElement | null = null; let activeElement: IActiveElement | null = null;
const manifest = await this.extensionManifest!.get().promise; const manifest = await this.extensionManifest!.get().promise;
if (manifest && manifest.extensionPack?.length && this.shallRenderAsExtensionPack(manifest)) { if (manifest && manifest.extensionPack?.length && this.shallRenderAsExtensionPack(manifest)) {
activeElement = await this.openExtensionPackReadme(extension, manifest, readmeContainer, token); activeElement = await this.openExtensionPackReadme(extension, manifest, contentContainer, token);
} else { } else {
activeElement = await this.openMarkdown(extension, this.extensionReadme!.get(), localize('noReadme', "No README available."), readmeContainer, WebviewIndex.Readme, localize('Readme title', "Readme"), token); activeElement = await this.openMarkdown(extension, this.extensionReadme!.get(), localize('noReadme', "No README available."), contentContainer, WebviewIndex.Readme, localize('Readme title', "Readme"), token);
} }
this.renderAdditionalDetails(additionalDetailsContainer, extension);
return activeElement; return activeElement;
} }
@@ -870,21 +873,35 @@ export class ExtensionEditor extends EditorPane {
extensionPackReadme.style.maxWidth = '882px'; extensionPackReadme.style.maxWidth = '882px';
const extensionPack = append(extensionPackReadme, $('div', { class: 'extension-pack' })); const extensionPack = append(extensionPackReadme, $('div', { class: 'extension-pack' }));
if (manifest.extensionPack!.length <= 3) {
extensionPackReadme.classList.add('one-row'); const packCount = manifest.extensionPack!.length;
} else if (manifest.extensionPack!.length <= 6) { const headerHeight = 37; // navbar height
extensionPackReadme.classList.add('two-rows'); const contentMinHeight = 200; // minimum height for readme content
} else if (manifest.extensionPack!.length <= 9) {
extensionPackReadme.classList.add('three-rows'); const layout = () => {
} else { extensionPackReadme.classList.remove('one-row', 'two-rows', 'three-rows', 'more-rows');
extensionPackReadme.classList.add('more-rows'); const availableHeight = container.clientHeight;
} const availableForPack = Math.max(availableHeight - headerHeight - contentMinHeight, 0);
let rowClass = 'one-row';
if (availableForPack >= 302 && packCount > 6) {
rowClass = 'more-rows';
} else if (availableForPack >= 282 && packCount > 4) {
rowClass = 'three-rows';
} else if (availableForPack >= 200 && packCount > 2) {
rowClass = 'two-rows';
} else {
rowClass = 'one-row';
}
extensionPackReadme.classList.add(rowClass);
};
layout();
this.contentDisposables.add(toDisposable(arrays.insert(this.layoutParticipants, { layout })));
const extensionPackHeader = append(extensionPack, $('div.header')); const extensionPackHeader = append(extensionPack, $('div.header'));
extensionPackHeader.textContent = localize('extension pack', "Extension Pack ({0})", manifest.extensionPack!.length); extensionPackHeader.textContent = localize('extension pack', "Extension Pack ({0})", manifest.extensionPack!.length);
const extensionPackContent = append(extensionPack, $('div', { class: 'extension-pack-content' })); const extensionPackContent = append(extensionPack, $('div', { class: 'extension-pack-content' }));
extensionPackContent.setAttribute('tabindex', '0'); extensionPackContent.setAttribute('tabindex', '0');
append(extensionPack, $('div.footer'));
const readmeContent = append(extensionPackReadme, $('div.readme-content')); const readmeContent = append(extensionPackReadme, $('div.readme-content'));
await Promise.all([ await Promise.all([
@@ -909,12 +926,14 @@ export class ExtensionEditor extends EditorPane {
scrollableContent.scanDomNode(); scrollableContent.scanDomNode();
} }
private openChangelog(extension: IExtension, template: IExtensionEditorTemplate, token: CancellationToken): Promise<IActiveElement | null> { private async openChangelog(extension: IExtension, contentContainer: HTMLElement, token: CancellationToken): Promise<IActiveElement | null> {
return this.openMarkdown(extension, this.extensionChangelog!.get(), localize('noChangelog', "No Changelog available."), template.content, WebviewIndex.Changelog, localize('Changelog title', "Changelog"), token); const activeElement = await this.openMarkdown(extension, this.extensionChangelog!.get(), localize('noChangelog', "No Changelog available."), contentContainer, WebviewIndex.Changelog, localize('Changelog title', "Changelog"), token);
return activeElement;
} }
private async openFeatures(template: IExtensionEditorTemplate, token: CancellationToken): Promise<IActiveElement | null> { private async openFeatures(extension: IExtension, contentContainer: HTMLElement, token: CancellationToken): Promise<IActiveElement | null> {
const manifest = await this.loadContents(() => this.extensionManifest!.get(), template.content); const manifest = await this.loadContents(() => this.extensionManifest!.get(), contentContainer);
if (token.isCancellationRequested) { if (token.isCancellationRequested) {
return null; return null;
} }
@@ -923,27 +942,28 @@ export class ExtensionEditor extends EditorPane {
} }
const extensionFeaturesTab = this.contentDisposables.add(this.instantiationService.createInstance(ExtensionFeaturesTab, manifest, (<IExtensionEditorOptions | undefined>this.options)?.feature)); const extensionFeaturesTab = this.contentDisposables.add(this.instantiationService.createInstance(ExtensionFeaturesTab, manifest, (<IExtensionEditorOptions | undefined>this.options)?.feature));
const layout = () => extensionFeaturesTab.layout(template.content.clientHeight, template.content.clientWidth); const featureLayout = () => extensionFeaturesTab.layout(contentContainer.clientHeight, contentContainer.clientWidth);
const removeLayoutParticipant = arrays.insert(this.layoutParticipants, { layout }); const removeLayoutParticipant = arrays.insert(this.layoutParticipants, { layout: featureLayout });
this.contentDisposables.add(toDisposable(removeLayoutParticipant)); this.contentDisposables.add(toDisposable(removeLayoutParticipant));
append(template.content, extensionFeaturesTab.domNode); append(contentContainer, extensionFeaturesTab.domNode);
layout(); featureLayout();
return extensionFeaturesTab.domNode; return extensionFeaturesTab.domNode;
} }
private openExtensionDependencies(extension: IExtension, template: IExtensionEditorTemplate, token: CancellationToken): Promise<IActiveElement | null> { private openExtensionDependencies(extension: IExtension, contentContainer: HTMLElement, token: CancellationToken): Promise<IActiveElement | null> {
if (token.isCancellationRequested) { if (token.isCancellationRequested) {
return Promise.resolve(null); return Promise.resolve(null);
} }
if (arrays.isFalsyOrEmpty(extension.dependencies)) { if (arrays.isFalsyOrEmpty(extension.dependencies)) {
append(template.content, $('p.nocontent')).textContent = localize('noDependencies', "No Dependencies"); append(contentContainer, $('p.nocontent')).textContent = localize('noDependencies', "No Dependencies");
return Promise.resolve(template.content); return Promise.resolve(contentContainer);
} }
const content = $('div', { class: 'subcontent' }); const content = $('div', { class: 'subcontent' });
const scrollableContent = new DomScrollableElement(content, {}); const scrollableContent = new DomScrollableElement(content, {});
append(template.content, scrollableContent.getDomNode()); append(contentContainer, scrollableContent.getDomNode());
this.contentDisposables.add(scrollableContent); this.contentDisposables.add(scrollableContent);
const dependenciesTree = this.instantiationService.createInstance(ExtensionsTree, const dependenciesTree = this.instantiationService.createInstance(ExtensionsTree,
@@ -951,31 +971,34 @@ export class ExtensionEditor extends EditorPane {
{ {
listBackground: editorBackground listBackground: editorBackground
}); });
const layout = () => { const depLayout = () => {
scrollableContent.scanDomNode(); scrollableContent.scanDomNode();
const scrollDimensions = scrollableContent.getScrollDimensions(); const scrollDimensions = scrollableContent.getScrollDimensions();
dependenciesTree.layout(scrollDimensions.height); dependenciesTree.layout(scrollDimensions.height);
}; };
const removeLayoutParticipant = arrays.insert(this.layoutParticipants, { layout }); const removeLayoutParticipant = arrays.insert(this.layoutParticipants, { layout: depLayout });
this.contentDisposables.add(toDisposable(removeLayoutParticipant)); this.contentDisposables.add(toDisposable(removeLayoutParticipant));
this.contentDisposables.add(dependenciesTree); this.contentDisposables.add(dependenciesTree);
scrollableContent.scanDomNode(); scrollableContent.scanDomNode();
return Promise.resolve({ focus() { dependenciesTree.domFocus(); } }); return Promise.resolve({ focus() { dependenciesTree.domFocus(); } });
} }
private async openExtensionPack(extension: IExtension, template: IExtensionEditorTemplate, token: CancellationToken): Promise<IActiveElement | null> { private async openExtensionPack(extension: IExtension, contentContainer: HTMLElement, token: CancellationToken): Promise<IActiveElement | null> {
if (token.isCancellationRequested) { if (token.isCancellationRequested) {
return Promise.resolve(null); return Promise.resolve(null);
} }
const manifest = await this.loadContents(() => this.extensionManifest!.get(), template.content);
const manifest = await this.loadContents(() => this.extensionManifest!.get(), contentContainer);
if (token.isCancellationRequested) { if (token.isCancellationRequested) {
return null; return null;
} }
if (!manifest) { if (!manifest) {
return null; return null;
} }
return this.renderExtensionPack(manifest, template.content, token);
return this.renderExtensionPack(manifest, contentContainer, token);
} }
private async renderExtensionPack(manifest: IExtensionManifest, parent: HTMLElement, token: CancellationToken): Promise<IActiveElement | null> { private async renderExtensionPack(manifest: IExtensionManifest, parent: HTMLElement, token: CancellationToken): Promise<IActiveElement | null> {

View File

@@ -431,14 +431,14 @@
display: flex; display: flex;
} }
.extension-editor > .body > .content > .details > .readme-container { .extension-editor > .body > .content > .details > .content-container {
margin: 0px auto; margin: 0px auto;
max-width: 75%; max-width: 75%;
height: 100%; height: 100%;
flex: 1; flex: 1;
} }
.extension-editor > .body > .content > .details.narrow > .readme-container { .extension-editor > .body > .content > .details.narrow > .content-container {
margin: inherit; margin: inherit;
max-width: inherit; max-width: inherit;
} }
@@ -526,67 +526,66 @@
padding: 0px; padding: 0px;
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme {
height: 100%; height: 100%;
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme > .extension-pack { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme > .extension-pack {
height: 224px; height: 200px;
padding-left: 20px; padding-left: 20px;
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme.one-row > .extension-pack { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme.one-row > .extension-pack {
height: 142px; height: 118px;
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme.two-rows > .extension-pack { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme.two-rows > .extension-pack {
height: 224px; height: 200px;
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme.three-rows > .extension-pack { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme.three-rows > .extension-pack {
height: 306px; height: 282px;
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme.more-rows > .extension-pack { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme.more-rows > .extension-pack {
height: 326px; height: 302px;
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme.one-row > .readme-content { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme.one-row > .readme-content {
height: calc(100% - 142px); height: calc(100% - 118px);
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme.two-rows > .readme-content { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme.two-rows > .readme-content {
height: calc(100% - 224px); height: calc(100% - 200px);
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme.three-rows > .readme-content { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme.three-rows > .readme-content {
height: calc(100% - 306px); height: calc(100% - 282px);
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme.more-rows > .readme-content { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme.more-rows > .readme-content {
height: calc(100% - 326px); height: calc(100% - 302px);
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme > .extension-pack > .header, .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme > .extension-pack > .header {
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme > .extension-pack > .footer {
margin-bottom: 10px;
margin-right: 30px; margin-right: 30px;
font-weight: bold; font-weight: bold;
font-size: 120%; font-size: 120%;
border-bottom: 1px solid rgba(128, 128, 128, 0.22); padding: 6px;
padding: 4px 6px;
line-height: 22px; line-height: 22px;
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme > .extension-pack > .extension-pack-content { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme > .extension-pack > .extension-pack-content {
height: calc(100% - 60px); height: calc(100% - 34px);
border-top: 1px solid rgba(128, 128, 128, 0.22);
border-bottom: 1px solid rgba(128, 128, 128, 0.22);
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme > .extension-pack > .extension-pack-content > .monaco-scrollable-element { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme > .extension-pack > .extension-pack-content > .monaco-scrollable-element {
height: 100%; height: 100%;
} }
.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme > .extension-pack > .extension-pack-content > .monaco-scrollable-element > .subcontent { .extension-editor > .body > .content > .details > .content-container > .extension-pack-readme > .extension-pack > .extension-pack-content > .monaco-scrollable-element > .subcontent {
height: 100%; height: 100%;
overflow-y: scroll; overflow-y: scroll;
box-sizing: border-box; box-sizing: border-box;
@@ -757,7 +756,7 @@
.extension-editor .extensions-grid-view > .extension-container { .extension-editor .extensions-grid-view > .extension-container {
width: 350px; width: 350px;
margin: 0 10px 20px 0; margin: 5px 10px;
} }
.extension-editor .extensions-grid-view .extension-list-item { .extension-editor .extensions-grid-view .extension-list-item {