Add "new extensions" settings results button for #49474, but disabled for now

This commit is contained in:
Rob Lourens 2018-07-26 19:47:08 -07:00
parent f303b02376
commit a9589652c1
6 changed files with 106 additions and 22 deletions

View file

@ -2752,13 +2752,16 @@ CommandsRegistry.registerCommand('workbench.extensions.action.showExtensionsForL
});
});
CommandsRegistry.registerCommand('workbench.extensions.action.showExtensionsWithId', function (accessor: ServicesAccessor, extensionId: string) {
CommandsRegistry.registerCommand('workbench.extensions.action.showExtensionsWithIds', function (accessor: ServicesAccessor, extensionIds: string[]) {
const viewletService = accessor.get(IViewletService);
return viewletService.openViewlet(VIEWLET_ID, true)
.then(viewlet => viewlet as IExtensionsViewlet)
.then(viewlet => {
viewlet.search(`@id:${extensionId}`);
const query = extensionIds
.map(id => `@id:${id}`)
.join(' ');
viewlet.search(query);
viewlet.focus();
});
});

View file

@ -227,12 +227,16 @@ export class ExtensionsListView extends ViewletPanel {
return new PagedModel(this.sortExtensions(result, options));
}
const idMatch = /@id:(([a-z0-9A-Z][a-z0-9\-A-Z]*)\.([a-z0-9A-Z][a-z0-9\-A-Z]*))/.exec(value);
if (idMatch) {
const idRegex = /@id:(([a-z0-9A-Z][a-z0-9\-A-Z]*)\.([a-z0-9A-Z][a-z0-9\-A-Z]*))/g;
let idMatch;
const names: string[] = [];
while ((idMatch = idRegex.exec(value)) !== null) {
const name = idMatch[1];
names.push(name);
}
return this.extensionsWorkbenchService.queryGallery({ names: [name], source: 'queryById' })
if (names.length) {
return this.extensionsWorkbenchService.queryGallery({ names, source: 'queryById' })
.then(pager => new PagedModel(pager));
}

View file

@ -148,9 +148,8 @@
.settings-editor > .settings-body .settings-toc-container {
width: 160px;
padding-top: 5px;
margin-top: 5px;
padding-left: 5px;
box-sizing: border-box;
}
.settings-editor > .settings-body .settings-toc-container.hidden {
@ -201,8 +200,7 @@
flex: 1;
max-width: 792px;
margin-right: 1px; /* So the item doesn't blend into the edge of the view container */
padding-top: 8px;
box-sizing: border-box;
margin-top: 8px;
border-spacing: 0;
border-collapse: separate;
position: relative;
@ -330,6 +328,16 @@
height: 26px;
}
.settings-editor > .settings-body > .settings-tree-container .setting-item-new-extensions {
display: flex;
}
.settings-editor > .settings-body > .settings-tree-container .setting-item-new-extensions .settings-new-extensions-button {
margin: auto;
width: initial;
padding: 4px 10px;
}
.settings-editor > .settings-body > .settings-tree-container .group-title,
.settings-editor > .settings-body > .settings-tree-container .setting-item {
padding-left: 9px;

View file

@ -737,17 +737,14 @@ export class SettingsEditor2 extends BaseEditor {
}
private filterOrSearchPreferences(query: string, type: SearchResultIdx, searchProvider: ISearchProvider): TPromise<void> {
const filterPs: TPromise<ISearchResult>[] = [this._filterOrSearchPreferencesModel(query, this.defaultSettingsEditorModel, searchProvider)];
let isCanceled = false;
return new TPromise(resolve => {
return TPromise.join(filterPs).then(results => {
return this._filterOrSearchPreferencesModel(query, this.defaultSettingsEditorModel, searchProvider).then(result => {
if (isCanceled) {
// Handle cancellation like this because cancellation is lost inside the search provider due to async/await
return null;
}
const [result] = results;
if (!this.searchResultModel) {
this.searchResultModel = this.instantiationService.createInstance(SearchResultModel, this.viewState);
this.searchResultModel.setResult(type, result);
@ -793,7 +790,7 @@ export class SettingsEditor2 extends BaseEditor {
private layoutTrees(dimension: DOM.Dimension): void {
const listHeight = dimension.height - (DOM.getDomNodePagePosition(this.headerContainer).height + 11 /*padding*/);
this.settingsTreeContainer.style.height = `${listHeight}px`;
this.settingsTree.layout(listHeight, 800);
this.settingsTree.layout(listHeight - 8, 800);
const selectedSetting = this.settingsTree.getSelection()[0];
if (selectedSetting) {
@ -801,7 +798,7 @@ export class SettingsEditor2 extends BaseEditor {
}
this.tocTreeContainer.style.height = `${listHeight}px`;
this.tocTree.layout(listHeight, 175);
this.tocTree.layout(listHeight - 5, 175);
}
}

View file

@ -24,6 +24,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { IAccessibilityProvider, IDataSource, IFilter, IRenderer as ITreeRenderer, ITree, ITreeConfiguration } from 'vs/base/parts/tree/browser/tree';
import { DefaultTreestyler } from 'vs/base/parts/tree/browser/treeDefaults';
import { localize } from 'vs/nls';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
@ -35,8 +36,8 @@ import { attachButtonStyler, attachInputBoxStyler, attachSelectBoxStyler, attach
import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { SettingsTarget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets';
import { ITOCEntry } from 'vs/workbench/parts/preferences/browser/settingsLayout';
import { ExcludeSettingWidget, settingsNumberInputBackground, settingsNumberInputBorder, settingsNumberInputForeground, settingsSelectBackground, settingsSelectBorder, settingsSelectForeground, settingsTextInputBorder, settingsTextInputForeground, settingItemInactiveSelectionBorder, settingsHeaderForeground, settingsTextInputBackground, IExcludeDataItem } from 'vs/workbench/parts/preferences/browser/settingsWidgets';
import { ISearchResult, ISetting, ISettingsGroup } from 'vs/workbench/services/preferences/common/preferences';
import { ExcludeSettingWidget, IExcludeDataItem, settingItemInactiveSelectionBorder, settingsHeaderForeground, settingsNumberInputBackground, settingsNumberInputBorder, settingsNumberInputForeground, settingsSelectBackground, settingsSelectBorder, settingsSelectForeground, settingsTextInputBackground, settingsTextInputBorder, settingsTextInputForeground } from 'vs/workbench/parts/preferences/browser/settingsWidgets';
import { IExtensionSetting, ISearchResult, ISetting, ISettingsGroup } from 'vs/workbench/services/preferences/common/preferences';
const $ = DOM.$;
@ -55,6 +56,10 @@ export class SettingsTreeGroupElement extends SettingsTreeElement {
isFirstGroup: boolean;
}
export class SettingsTreeNewExtensionsElement extends SettingsTreeElement {
extensionIds: string[];
}
export class SettingsTreeSettingElement extends SettingsTreeElement {
setting: ISetting;
@ -494,6 +499,11 @@ interface ISettingExcludeItemTemplate extends ISettingItemTemplate<void> {
context?: SettingsTreeSettingElement;
}
interface ISettingNewExtensionsTemplate extends IDisposableTemplate {
button: Button;
context?: SettingsTreeNewExtensionsElement;
}
function isExcludeSetting(setting: ISetting): boolean {
return setting.key === 'files.exclude' ||
setting.key === 'search.exclude';
@ -510,6 +520,7 @@ const SETTINGS_ENUM_TEMPLATE_ID = 'settings.enum.template';
const SETTINGS_BOOL_TEMPLATE_ID = 'settings.bool.template';
const SETTINGS_EXCLUDE_TEMPLATE_ID = 'settings.exclude.template';
const SETTINGS_COMPLEX_TEMPLATE_ID = 'settings.complex.template';
const SETTINGS_NEW_EXTENSIONS_TEMPLATE_ID = 'settings.newExtensions.template';
const SETTINGS_GROUP_ELEMENT_TEMPLATE_ID = 'settings.group.template';
export interface ISettingChangeEvent {
@ -540,6 +551,7 @@ export class SettingsRenderer implements ITreeRenderer {
@IContextViewService private contextViewService: IContextViewService,
@IOpenerService private readonly openerService: IOpenerService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@ICommandService private readonly commandService: ICommandService,
) {
this.measureContainer = DOM.append(_measureContainer, $('.setting-measure-container.monaco-tree-row'));
}
@ -564,6 +576,10 @@ export class SettingsRenderer implements ITreeRenderer {
}
}
if (element instanceof SettingsTreeNewExtensionsElement) {
return 40;
}
return 0;
}
@ -622,6 +638,10 @@ export class SettingsRenderer implements ITreeRenderer {
return SETTINGS_COMPLEX_TEMPLATE_ID;
}
if (element instanceof SettingsTreeNewExtensionsElement) {
return SETTINGS_NEW_EXTENSIONS_TEMPLATE_ID;
}
return '';
}
@ -654,6 +674,10 @@ export class SettingsRenderer implements ITreeRenderer {
return this.renderSettingComplexTemplate(tree, container);
}
if (templateId === SETTINGS_NEW_EXTENSIONS_TEMPLATE_ID) {
return this.renderNewExtensionsTemplate(container);
}
return null;
}
@ -911,11 +935,39 @@ export class SettingsRenderer implements ITreeRenderer {
return template;
}
private renderNewExtensionsTemplate(container: HTMLElement): ISettingNewExtensionsTemplate {
const toDispose = [];
container.classList.add('setting-item-new-extensions');
const button = new Button(container, { title: true, buttonBackground: null, buttonHoverBackground: null });
toDispose.push(button);
toDispose.push(button.onDidClick(() => {
if (template.context) {
this.commandService.executeCommand('workbench.extensions.action.showExtensionsWithIds', template.context.extensionIds);
}
}));
button.label = localize('newExtensionsButtonLabel', "Show other matching extensions");
button.element.classList.add('settings-new-extensions-button');
toDispose.push(attachButtonStyler(button, this.themeService));
const template: ISettingNewExtensionsTemplate = {
button,
toDispose
};
return template;
}
renderElement(tree: ITree, element: SettingsTreeElement, templateId: string, template: any): void {
if (templateId === SETTINGS_GROUP_ELEMENT_TEMPLATE_ID) {
return this.renderGroupElement(<SettingsTreeGroupElement>element, template);
}
if (templateId === SETTINGS_NEW_EXTENSIONS_TEMPLATE_ID) {
return this.renderNewExtensionsElement(<SettingsTreeNewExtensionsElement>element, template);
}
return this.renderSettingElement(tree, <SettingsTreeSettingElement>element, templateId, template);
}
@ -936,6 +988,10 @@ export class SettingsRenderer implements ITreeRenderer {
return selectedElement && selectedElement.id === element.id;
}
private renderNewExtensionsElement(element: SettingsTreeNewExtensionsElement, template: ISettingNewExtensionsTemplate): void {
template.context = element;
}
private renderSettingElement(tree: ITree, element: SettingsTreeSettingElement, templateId: string, template: ISettingItemTemplate | ISettingBoolItemTemplate): void {
const isSelected = !!this.elementIsSelected(tree, element);
const setting = element.setting;
@ -1198,13 +1254,15 @@ export class SettingsAccessibilityProvider implements IAccessibilityProvider {
export enum SearchResultIdx {
Local = 0,
Remote = 1
Remote = 1,
NewExtensions = 2
}
export class SearchResultModel {
private rawSearchResults: ISearchResult[];
private cachedUniqueSearchResults: ISearchResult[];
private children: SettingsTreeSettingElement[];
private newExtensionSearchResults: ISearchResult;
private children: (SettingsTreeSettingElement | SettingsTreeNewExtensionsElement)[];
readonly id = 'searchResultModel';
@ -1213,7 +1271,7 @@ export class SearchResultModel {
@IConfigurationService private _configurationService: IConfigurationService
) { }
getChildren(): SettingsTreeSettingElement[] {
getChildren(): (SettingsTreeSettingElement | SettingsTreeNewExtensionsElement)[] {
return this.children;
}
@ -1237,6 +1295,8 @@ export class SearchResultModel {
remoteResult.filterMatches = remoteResult.filterMatches.filter(m => !localMatchKeys.has(m.setting.key));
}
this.newExtensionSearchResults = objects.deepClone(this.rawSearchResults[SearchResultIdx.NewExtensions]);
this.cachedUniqueSearchResults = [localResult, remoteResult];
return this.cachedUniqueSearchResults;
}
@ -1260,6 +1320,18 @@ export class SearchResultModel {
updateChildren(): void {
this.children = this.getFlatSettings()
.map(s => createSettingsTreeSettingElement(s, this, this._viewState.settingsTarget, this._configurationService));
if (this.newExtensionSearchResults) {
const newExtElement = new SettingsTreeNewExtensionsElement();
newExtElement.parent = this;
newExtElement.id = 'newExtensions';
const resultExtensionIds = this.newExtensionSearchResults.filterMatches
.map(result => (<IExtensionSetting>result.setting))
.filter(setting => setting.extensionName && setting.extensionPublisher)
.map(setting => `${setting.extensionPublisher}.${setting.extensionName}`);
newExtElement.extensionIds = arrays.distinct(resultExtensionIds);
this.children.push(newExtElement);
}
}
private getFlatSettings(): ISetting[] {

View file

@ -49,7 +49,7 @@ export class TOCTreeModel {
private getSearchResultChildrenCount(group: SettingsTreeGroupElement): number {
return this._currentSearchModel.getChildren().filter(child => {
return this.groupContainsSetting(group, child.setting);
return child instanceof SettingsTreeSettingElement && this.groupContainsSetting(group, child.setting);
}).length;
}