提交 91198d94 编写于 作者: R Rob Lourens

Request settings for new extensions

上级 1c6d46db
...@@ -111,7 +111,7 @@ export class PreferencesEditor extends BaseEditor { ...@@ -111,7 +111,7 @@ export class PreferencesEditor extends BaseEditor {
private preferencesRenderers: PreferencesRenderersController; private preferencesRenderers: PreferencesRenderersController;
private delayedFilterLogging: Delayer<void>; private delayedFilterLogging: Delayer<void>;
private remoteSearchThrottle: ThrottledDelayer<IFilterOrSearchResult>; private remoteSearchThrottle: ThrottledDelayer<void>;
private _lastReportedFilter: string; private _lastReportedFilter: string;
private lastFocusedWidget: SearchWidget | SideBySidePreferencesWidget = null; private lastFocusedWidget: SearchWidget | SideBySidePreferencesWidget = null;
...@@ -243,18 +243,18 @@ export class PreferencesEditor extends BaseEditor { ...@@ -243,18 +243,18 @@ export class PreferencesEditor extends BaseEditor {
TPromise.join([ TPromise.join([
this.preferencesRenderers.localFilterPreferences(query), this.preferencesRenderers.localFilterPreferences(query),
this.triggerThrottledSearch(query) this.triggerThrottledSearch(query)
]).then(results => { ]).then(() => {
if (results) { const result = this.preferencesRenderers.lastFilterResult;
const [localResult, remoteResult] = results; if (result) {
this.delayedFilterLogging.trigger(() => this.reportFilteringUsed( this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(
query, query,
remoteResult ? remoteResult.defaultSettingsGroupCounts : localResult.defaultSettingsGroupCounts, result.defaultSettingsGroupCounts,
remoteResult && remoteResult.metadata)); result.metadata));
} }
}); });
} }
private triggerThrottledSearch(query: string): TPromise<IFilterOrSearchResult> { private triggerThrottledSearch(query: string): TPromise<void> {
if (query) { if (query) {
return this.remoteSearchThrottle.trigger(() => this.preferencesRenderers.remoteSearchPreferences(query)); return this.remoteSearchThrottle.trigger(() => this.preferencesRenderers.remoteSearchPreferences(query));
} else { } else {
...@@ -366,11 +366,13 @@ class PreferencesRenderersController extends Disposable { ...@@ -366,11 +366,13 @@ class PreferencesRenderersController extends Disposable {
private _editablePreferencesRendererDisposables: IDisposable[] = []; private _editablePreferencesRendererDisposables: IDisposable[] = [];
private _settingsNavigator: SettingsNavigator; private _settingsNavigator: SettingsNavigator;
private _filtersInProgress: TPromise<IFilterResult>[]; private _remoteFiltersInProgress: TPromise<any>[];
private _currentLocalSearchProvider: ISearchProvider; private _currentLocalSearchProvider: ISearchProvider;
private _currentRemoteSearchProvider: ISearchProvider; private _currentRemoteSearchProvider: ISearchProvider;
private _currentNewExtensionsSearchProvider: ISearchProvider;
private _lastQuery: string; private _lastQuery: string;
private _lastFilterResult: IFilterOrSearchResult;
private _onDidFilterResultsCountChange: Emitter<number> = this._register(new Emitter<number>()); private _onDidFilterResultsCountChange: Emitter<number> = this._register(new Emitter<number>());
public onDidFilterResultsCountChange: Event<number> = this._onDidFilterResultsCountChange.event; public onDidFilterResultsCountChange: Event<number> = this._onDidFilterResultsCountChange.event;
...@@ -382,6 +384,10 @@ class PreferencesRenderersController extends Disposable { ...@@ -382,6 +384,10 @@ class PreferencesRenderersController extends Disposable {
super(); super();
} }
get lastFilterResult(): IFilterOrSearchResult {
return this._lastFilterResult;
}
get defaultPreferencesRenderer(): IPreferencesRenderer<ISetting> { get defaultPreferencesRenderer(): IPreferencesRenderer<ISetting> {
return this._defaultPreferencesRenderer; return this._defaultPreferencesRenderer;
} }
...@@ -415,34 +421,48 @@ class PreferencesRenderersController extends Disposable { ...@@ -415,34 +421,48 @@ class PreferencesRenderersController extends Disposable {
} }
} }
async _onEditableContentDidChange(): TPromise<void> { private async _onEditableContentDidChange(): TPromise<void> {
await this.localFilterPreferences(this._lastQuery, true); await this.localFilterPreferences(this._lastQuery, true);
await this.remoteSearchPreferences(this._lastQuery, true); await this.remoteSearchPreferences(this._lastQuery, true);
} }
remoteSearchPreferences(query: string, updateCurrentResults?: boolean): TPromise<IFilterOrSearchResult> { remoteSearchPreferences(query: string, updateCurrentResults?: boolean): TPromise<void> {
if (this._remoteFiltersInProgress) {
// Resolved/rejected promises have no .cancel()
this._remoteFiltersInProgress.forEach(p => p.cancel && p.cancel());
}
this._currentRemoteSearchProvider = (updateCurrentResults && this._currentRemoteSearchProvider) || this.preferencesSearchService.getRemoteSearchProvider(query); this._currentRemoteSearchProvider = (updateCurrentResults && this._currentRemoteSearchProvider) || this.preferencesSearchService.getRemoteSearchProvider(query);
return this.filterOrSearchPreferences(query, this._currentRemoteSearchProvider, 'nlpResult', nls.localize('nlpResult', "Natural Language Results")); this._currentNewExtensionsSearchProvider = (updateCurrentResults && this._currentNewExtensionsSearchProvider) || this.preferencesSearchService.getRemoteSearchProvider(query, true);
this._remoteFiltersInProgress = [
this.filterOrSearchPreferences(query, this._currentNewExtensionsSearchProvider, 'newExtensionsResult', nls.localize('newExtensionsResult', "Other Extension Results")),
this.filterOrSearchPreferences(query, this._currentRemoteSearchProvider, 'nlpResult', nls.localize('nlpResult', "Natural Language Results"))
];
return TPromise.join(this._remoteFiltersInProgress).then(() => {
this._remoteFiltersInProgress = null;
}, err => {
if (isPromiseCanceledError(err)) {
return null;
} else {
onUnexpectedError(err);
}
});
} }
localFilterPreferences(query: string, updateCurrentResults?: boolean): TPromise<IFilterOrSearchResult> { localFilterPreferences(query: string, updateCurrentResults?: boolean): TPromise<void> {
this._currentLocalSearchProvider = (updateCurrentResults && this._currentLocalSearchProvider) || this.preferencesSearchService.getLocalSearchProvider(query); this._currentLocalSearchProvider = (updateCurrentResults && this._currentLocalSearchProvider) || this.preferencesSearchService.getLocalSearchProvider(query);
return this.filterOrSearchPreferences(query, this._currentLocalSearchProvider, 'filterResult', nls.localize('filterResult', "Filtered Results")); return this.filterOrSearchPreferences(query, this._currentLocalSearchProvider, 'filterResult', nls.localize('filterResult', "Filtered Results"));
} }
filterOrSearchPreferences(query: string, searchProvider: ISearchProvider, groupId: string, groupLabel: string): TPromise<IFilterOrSearchResult> { private filterOrSearchPreferences(query: string, searchProvider: ISearchProvider, groupId: string, groupLabel: string): TPromise<void> {
this._lastQuery = query; this._lastQuery = query;
if (this._filtersInProgress) {
// Resolved/rejected promises have no .cancel()
this._filtersInProgress.forEach(p => p.cancel && p.cancel());
}
this._filtersInProgress = [ return TPromise.join([
this._filterOrSearchPreferences(query, this.defaultPreferencesRenderer, searchProvider, groupId, groupLabel), this._filterOrSearchPreferences(query, this.defaultPreferencesRenderer, searchProvider, groupId, groupLabel),
this._filterOrSearchPreferences(query, this.editablePreferencesRenderer, searchProvider, groupId, groupLabel)]; this._filterOrSearchPreferences(query, this.editablePreferencesRenderer, searchProvider, groupId, groupLabel)]
).then(results => {
return TPromise.join(this._filtersInProgress).then(results => {
this._filtersInProgress = null;
const [defaultFilterResult, editableFilterResult] = results; const [defaultFilterResult, editableFilterResult] = results;
this.consolidateAndUpdate(defaultFilterResult, editableFilterResult); this.consolidateAndUpdate(defaultFilterResult, editableFilterResult);
...@@ -451,13 +471,7 @@ class PreferencesRenderersController extends Disposable { ...@@ -451,13 +471,7 @@ class PreferencesRenderersController extends Disposable {
defaultSettingsGroupCounts: defaultFilterResult && this._countById(defaultFilterResult.filteredGroups) defaultSettingsGroupCounts: defaultFilterResult && this._countById(defaultFilterResult.filteredGroups)
}; };
return result; this._lastFilterResult = result;
}, err => {
if (isPromiseCanceledError(err)) {
return null;
} else {
onUnexpectedError(err);
}
}); });
} }
......
...@@ -177,7 +177,7 @@ export interface IPreferencesSearchService { ...@@ -177,7 +177,7 @@ export interface IPreferencesSearchService {
_serviceBrand: any; _serviceBrand: any;
getLocalSearchProvider(filter: string): ISearchProvider; getLocalSearchProvider(filter: string): ISearchProvider;
getRemoteSearchProvider(filter: string): ISearchProvider; getRemoteSearchProvider(filter: string, newExtensionsOnly?: boolean): ISearchProvider;
} }
export interface ISearchProvider { export interface ISearchProvider {
......
...@@ -67,8 +67,8 @@ export class PreferencesSearchService extends Disposable implements IPreferences ...@@ -67,8 +67,8 @@ export class PreferencesSearchService extends Disposable implements IPreferences
} }
} }
getRemoteSearchProvider(filter: string): RemoteSearchProvider { getRemoteSearchProvider(filter: string, newExtensionsOnly = false): RemoteSearchProvider {
return this.remoteSearchAllowed && this.instantiationService.createInstance(RemoteSearchProvider, filter, this._endpoint, this._installedExtensions); return this.remoteSearchAllowed && this.instantiationService.createInstance(RemoteSearchProvider, filter, this._endpoint, this._installedExtensions, newExtensionsOnly);
} }
getLocalSearchProvider(filter: string): LocalSearchProvider { getLocalSearchProvider(filter: string): LocalSearchProvider {
...@@ -117,7 +117,7 @@ export class RemoteSearchProvider implements ISearchProvider { ...@@ -117,7 +117,7 @@ export class RemoteSearchProvider implements ISearchProvider {
private _filter: string; private _filter: string;
private _remoteSearchP: TPromise<IFilterMetadata>; private _remoteSearchP: TPromise<IFilterMetadata>;
constructor(filter: string, endpoint: IEndpointDetails, private installedExtensions: TPromise<ILocalExtension[]>, constructor(filter: string, private endpoint: IEndpointDetails, private installedExtensions: TPromise<ILocalExtension[]>, private newExtensionsOnly: boolean,
@IEnvironmentService private environmentService: IEnvironmentService, @IEnvironmentService private environmentService: IEnvironmentService,
@IRequestService private requestService: IRequestService, @IRequestService private requestService: IRequestService,
) { ) {
...@@ -125,7 +125,7 @@ export class RemoteSearchProvider implements ISearchProvider { ...@@ -125,7 +125,7 @@ export class RemoteSearchProvider implements ISearchProvider {
// @queries are always handled by local filter // @queries are always handled by local filter
this._remoteSearchP = filter && !strings.startsWith(filter, '@') ? this._remoteSearchP = filter && !strings.startsWith(filter, '@') ?
this.getSettingsFromBing(filter, endpoint) : this.getSettingsFromBing(filter) :
TPromise.wrap(null); TPromise.wrap(null);
} }
...@@ -148,15 +148,15 @@ export class RemoteSearchProvider implements ISearchProvider { ...@@ -148,15 +148,15 @@ export class RemoteSearchProvider implements ISearchProvider {
}); });
} }
private getSettingsFromBing(filter: string, endpoint: IEndpointDetails): TPromise<IFilterMetadata> { private getSettingsFromBing(filter: string): TPromise<IFilterMetadata> {
const start = Date.now(); const start = Date.now();
return this.prepareUrl(filter, endpoint, this.environmentService.settingsSearchBuildId).then(url => { return this.prepareUrl(filter).then(url => {
return this.requestService.request({ return this.requestService.request({
url, url,
headers: { headers: {
'User-Agent': 'request', 'User-Agent': 'request',
'Content-Type': 'application/json; charset=utf-8', 'Content-Type': 'application/json; charset=utf-8',
'api-key': endpoint.key 'api-key': this.endpoint.key
}, },
timeout: 5000 timeout: 5000
}).then(context => { }).then(context => {
...@@ -205,7 +205,7 @@ export class RemoteSearchProvider implements ISearchProvider { ...@@ -205,7 +205,7 @@ export class RemoteSearchProvider implements ISearchProvider {
}; };
} }
private prepareUrl(query: string, endpoint: IEndpointDetails, buildNumber: number): TPromise<string> { private prepareUrl(query: string): TPromise<string> {
query = escapeSpecialChars(query); query = escapeSpecialChars(query);
const boost = 10; const boost = 10;
const userQuery = `(${query})^${boost}`; const userQuery = `(${query})^${boost}`;
...@@ -214,41 +214,55 @@ export class RemoteSearchProvider implements ISearchProvider { ...@@ -214,41 +214,55 @@ export class RemoteSearchProvider implements ISearchProvider {
query = query.replace(/\ +/g, '~ ') + '~'; query = query.replace(/\ +/g, '~ ') + '~';
const encodedQuery = encodeURIComponent(userQuery + ' || ' + query); const encodedQuery = encodeURIComponent(userQuery + ' || ' + query);
let url = `${endpoint.urlBase}?`; let url = `${this.endpoint.urlBase}?`;
return this.installedExtensions.then(exts => { const buildNumber = this.environmentService.settingsSearchBuildId;
if (endpoint.key) { if (this.endpoint.key) {
url += `${API_VERSION}`; url += `${API_VERSION}&${QUERY_TYPE}`;
url += `&search=${encodedQuery}`; url += `&search=${encodedQuery}`;
const filters = exts.map(ext => {
const uuid = ext.identifier.uuid;
const versionString = ext.manifest.version
.split('.')
.map(versionPart => strings.pad(<any>versionPart, 10))
.join('');
return `(packageid eq '${uuid}' and startbuildno le '${versionString}' and endbuildno ge '${versionString}')`;
});
if (buildNumber) { if (this.newExtensionsOnly) {
filters.push(`(packageid eq 'core' and startbuildno le '${buildNumber}' and endbuildno ge '${buildNumber}')`); return TPromise.wrap(url);
url += `&$filter=${filters.join(' or ')}`;
}
} else { } else {
url += `query=${encodedQuery}`; return this.getVersionAndExtensionFilters(buildNumber).then(filters => {
url += `&$filter=${filters.join(' or ')}`;
return url;
});
}
} else {
url += `query=${encodedQuery}`;
if (buildNumber) { if (buildNumber) {
url += `&build=${buildNumber}`; url += `&build=${buildNumber}`;
} }
}
return TPromise.wrap(url);
}
private getVersionAndExtensionFilters(buildNumber?: number): TPromise<string[]> {
return this.installedExtensions.then(exts => {
const filters = exts.map(ext => {
const uuid = ext.identifier.uuid;
const versionString = ext.manifest.version
.split('.')
.map(versionPart => strings.pad(<any>versionPart, 10))
.join('');
return `(packageid eq '${uuid}' and startbuildno le '${versionString}' and endbuildno ge '${versionString}')`;
});
if (buildNumber) {
filters.push(`(packageid eq 'core' and startbuildno le '${buildNumber}' and endbuildno ge '${buildNumber}')`);
} }
return url; return filters;
}); });
} }
} }
const API_VERSION = 'api-version=2016-09-01-Preview'; const API_VERSION = 'api-version=2016-09-01-Preview';
const QUERY_TYPE = 'querytype=full';
function escapeSpecialChars(query: string): string { function escapeSpecialChars(query: string): string {
return query.replace(/\./g, ' ') return query.replace(/\./g, ' ')
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册