diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index 3422619e30b..1a54da045a7 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -24,13 +24,12 @@ import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; import { CodeEditor } from 'vs/editor/browser/codeEditor'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { - IPreferencesService, ISettingsGroup, ISetting, IFilterResult, + IPreferencesService, ISettingsGroup, ISetting, IFilterResult, IPreferencesSearchService, CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, SETTINGS_EDITOR_COMMAND_SEARCH, SETTINGS_EDITOR_COMMAND_FOCUS_FILE, ISettingsEditorModel, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_FOCUS_NEXT_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_PREVIOUS_SETTING, IFilterMetadata } from 'vs/workbench/parts/preferences/common/preferences'; import { SettingsEditorModel, DefaultSettingsEditorModel } from 'vs/workbench/parts/preferences/common/preferencesModels'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { SearchWidget, SettingsTargetsWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets'; -import { PreferencesSearchProvider } from 'vs/workbench/parts/preferences/browser/preferencesSearch'; import { ContextKeyExpr, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { registerEditorContribution, Command, IEditorContributionCtor } from 'vs/editor/browser/editorExtensions'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -106,7 +105,6 @@ export class PreferencesEditor extends BaseEditor { private settingsTargetsWidget: SettingsTargetsWidget; private sideBySidePreferencesWidget: SideBySidePreferencesWidget; private preferencesRenderers: PreferencesRenderers; - private searchProvider: PreferencesSearchProvider; private delayedFilterLogging: Delayer; private filterThrottle: ThrottledDelayer; @@ -117,6 +115,7 @@ export class PreferencesEditor extends BaseEditor { constructor( @IPreferencesService private preferencesService: IPreferencesService, + @IPreferencesSearchService private preferencesSearchService: IPreferencesSearchService, @ITelemetryService telemetryService: ITelemetryService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IContextKeyService private contextKeyService: IContextKeyService, @@ -129,7 +128,6 @@ export class PreferencesEditor extends BaseEditor { this.defaultSettingsEditorContextKey = CONTEXT_SETTINGS_EDITOR.bindTo(this.contextKeyService); this.focusSettingsContextKey = CONTEXT_SETTINGS_SEARCH_FOCUS.bindTo(this.contextKeyService); this.delayedFilterLogging = new Delayer(1000); - this.searchProvider = this.instantiationService.createInstance(PreferencesSearchProvider); this.filterThrottle = new ThrottledDelayer(200); this.memento = this.getMemento(storageService, Scope.WORKSPACE); } @@ -147,9 +145,9 @@ export class PreferencesEditor extends BaseEditor { showFuzzyToggle: true, showResultCount: true })); - this.searchWidget.setFuzzyToggleVisible(this.searchProvider.remoteSearchAllowed); + this.searchWidget.setFuzzyToggleVisible(this.preferencesSearchService.remoteSearchAllowed); this.searchWidget.fuzzyEnabled = this.memento['fuzzyEnabled']; - this._register(this.searchProvider.onRemoteSearchEnablementChanged(enabled => this.searchWidget.setFuzzyToggleVisible(enabled))); + this._register(this.preferencesSearchService.onRemoteSearchEnablementChanged(enabled => this.searchWidget.setFuzzyToggleVisible(enabled))); this._register(this.searchWidget.onDidChange(value => this.onInputChanged())); this._register(this.searchWidget.onFocus(() => this.lastFocusedWidget = this.searchWidget)); this.lastFocusedWidget = this.searchWidget; @@ -161,7 +159,7 @@ export class PreferencesEditor extends BaseEditor { this.sideBySidePreferencesWidget = this._register(this.instantiationService.createInstance(SideBySidePreferencesWidget, editorsContainer)); this._register(this.sideBySidePreferencesWidget.onFocus(() => this.lastFocusedWidget = this.sideBySidePreferencesWidget)); - this.preferencesRenderers = this._register(new PreferencesRenderers(this.searchProvider)); + this.preferencesRenderers = this._register(new PreferencesRenderers(this.preferencesSearchService)); this._register(this.workspaceContextService.onDidChangeWorkspaceFolders(() => this.onWorkspaceFoldersChanged())); this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => this.onWorkbenchStateChanged())); @@ -451,7 +449,7 @@ class PreferencesRenderers extends Disposable { public onDidFilterResultsCountChange: Event = this._onDidFilterResultsCountChange.event; constructor( - private searchProvider: PreferencesSearchProvider + private preferencesSearchService: IPreferencesSearchService ) { super(); } @@ -557,11 +555,11 @@ class PreferencesRenderers extends Disposable { private _filterPreferences(searchCriteria: ISearchCriteria, preferencesRenderer: IPreferencesRenderer): TPromise { if (preferencesRenderer) { - const searchModel = this.searchProvider.startSearch(searchCriteria.filter, searchCriteria.fuzzy); + const searchModel = this.preferencesSearchService.startSearch(searchCriteria.filter, searchCriteria.fuzzy); const prefSearchP = searchModel.filterPreferences(preferencesRenderer.preferencesModel); return prefSearchP.then(filterResult => { - preferencesRenderer.filterPreferences(filterResult, this.searchProvider.remoteSearchAllowed); + preferencesRenderer.filterPreferences(filterResult, this.preferencesSearchService.remoteSearchAllowed); return filterResult; }); } diff --git a/src/vs/workbench/parts/preferences/common/preferences.ts b/src/vs/workbench/parts/preferences/common/preferences.ts index ab71831e477..5fb5317f442 100644 --- a/src/vs/workbench/parts/preferences/common/preferences.ts +++ b/src/vs/workbench/parts/preferences/common/preferences.ts @@ -148,6 +148,27 @@ export function getSettingsTargetName(target: ConfigurationTarget, resource: URI return ''; } +export interface IEndpointDetails { + urlBase: string; + key?: string; +} + +export const IPreferencesSearchService = createDecorator('preferencesSearchService'); + +export interface IPreferencesSearchService { + _serviceBrand: any; + + remoteSearchAllowed: boolean; + endpoint: IEndpointDetails; + onRemoteSearchEnablementChanged: Event; + + startSearch(filter: string, remote: boolean): IPreferencesSearchModel; +} + +export interface IPreferencesSearchModel { + filterPreferences(preferencesModel: ISettingsEditorModel): TPromise; +} + export const CONTEXT_SETTINGS_EDITOR = new RawContextKey('inSettingsEditor', false); export const CONTEXT_SETTINGS_SEARCH_FOCUS = new RawContextKey('inSettingsSearch', false); export const CONTEXT_KEYBINDINGS_EDITOR = new RawContextKey('inKeybindings', false); diff --git a/src/vs/workbench/parts/preferences/browser/preferences.contribution.ts b/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.ts similarity index 96% rename from src/vs/workbench/parts/preferences/browser/preferences.contribution.ts rename to src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.ts index 29b0cd4d587..63eb663cf79 100644 --- a/src/vs/workbench/parts/preferences/browser/preferences.contribution.ts +++ b/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.ts @@ -18,7 +18,7 @@ import { DefaultPreferencesEditorInput, PreferencesEditor, PreferencesEditorInpu import { KeybindingsEditor, KeybindingsEditorInput } from 'vs/workbench/parts/preferences/browser/keybindingsEditor'; import { OpenGlobalSettingsAction, OpenGlobalKeybindingsAction, OpenGlobalKeybindingsFileAction, OpenWorkspaceSettingsAction, OpenFolderSettingsAction, ConfigureLanguageBasedSettingsAction, OPEN_FOLDER_SETTINGS_COMMAND } from 'vs/workbench/parts/preferences/browser/preferencesActions'; import { - IPreferencesService, IKeybindingsEditor, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_SEARCH, + IPreferencesService, IKeybindingsEditor, IPreferencesSearchService, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_SEARCH, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS } from 'vs/workbench/parts/preferences/common/preferences'; import { PreferencesService } from 'vs/workbench/parts/preferences/browser/preferencesService'; @@ -31,8 +31,10 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; +import { PreferencesSearchService } from 'vs/workbench/parts/preferences/electron-browser/preferencesSearch'; registerSingleton(IPreferencesService, PreferencesService); +registerSingleton(IPreferencesSearchService, PreferencesSearchService); Registry.as(EditorExtensions.Editors).registerEditor( new EditorDescriptor( diff --git a/src/vs/workbench/parts/preferences/browser/preferencesSearch.ts b/src/vs/workbench/parts/preferences/electron-browser/preferencesSearch.ts similarity index 89% rename from src/vs/workbench/parts/preferences/browser/preferencesSearch.ts rename to src/vs/workbench/parts/preferences/electron-browser/preferencesSearch.ts index 70a282d2e33..43b76998d8a 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesSearch.ts +++ b/src/vs/workbench/parts/preferences/electron-browser/preferencesSearch.ts @@ -5,7 +5,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import Event, { Emitter } from 'vs/base/common/event'; -import { ISettingsEditorModel, IFilterResult, ISetting, ISettingsGroup, IWorkbenchSettingsConfiguration, IFilterMetadata } from 'vs/workbench/parts/preferences/common/preferences'; +import { ISettingsEditorModel, IFilterResult, ISetting, ISettingsGroup, IWorkbenchSettingsConfiguration, IFilterMetadata, IPreferencesSearchService } from 'vs/workbench/parts/preferences/common/preferences'; import { IRange, Range } from 'vs/editor/common/core/range'; import { distinct } from 'vs/base/common/arrays'; import * as strings from 'vs/base/common/strings'; @@ -15,21 +15,29 @@ import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/co import { IMatch, or, matchesContiguousSubString, matchesPrefix, matchesCamelCase, matchesWords } from 'vs/base/common/filters'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IRequestService } from 'vs/platform/request/node/request'; +import { asJson } from 'vs/base/node/request'; +import { Disposable } from 'vs/base/common/lifecycle'; export interface IEndpointDetails { urlBase: string; key?: string; } -export class PreferencesSearchProvider { +export class PreferencesSearchService extends Disposable implements IPreferencesSearchService { + _serviceBrand: any; + private _onRemoteSearchEnablementChanged = new Emitter(); public onRemoteSearchEnablementChanged: Event = this._onRemoteSearchEnablementChanged.event; constructor( @IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService, - @IEnvironmentService private environmentService: IEnvironmentService + @IEnvironmentService private environmentService: IEnvironmentService, + @IInstantiationService private instantiationService: IInstantiationService ) { - configurationService.onDidChangeConfiguration(() => this._onRemoteSearchEnablementChanged.fire(this.remoteSearchAllowed)); + super(); + this._register(configurationService.onDidChangeConfiguration(() => this._onRemoteSearchEnablementChanged.fire(this.remoteSearchAllowed))); } get remoteSearchAllowed(): boolean { @@ -60,7 +68,7 @@ export class PreferencesSearchProvider { } startSearch(filter: string, remote: boolean): PreferencesSearchModel { - return new PreferencesSearchModel(this, filter, remote, this.environmentService); + return this.instantiationService.createInstance(PreferencesSearchModel, this, filter, remote); } } @@ -68,11 +76,14 @@ export class PreferencesSearchModel { private _localProvider: LocalSearchProvider; private _remoteProvider: RemoteSearchProvider; - constructor(private provider: PreferencesSearchProvider, private filter: string, remote: boolean, environmentService: IEnvironmentService) { + constructor( + private provider: IPreferencesSearchService, private filter: string, remote: boolean, + @IInstantiationService instantiationService: IInstantiationService + ) { this._localProvider = new LocalSearchProvider(filter); if (remote && filter) { - this._remoteProvider = new RemoteSearchProvider(filter, this.provider.endpoint, environmentService); + this._remoteProvider = instantiationService.createInstance(RemoteSearchProvider, filter, this.provider.endpoint); } } @@ -117,7 +128,10 @@ class RemoteSearchProvider { private _filter: string; private _remoteSearchP: TPromise; - constructor(filter: string, endpoint: IEndpointDetails, private environmentService: IEnvironmentService) { + constructor(filter: string, endpoint: IEndpointDetails, + @IEnvironmentService private environmentService: IEnvironmentService, + @IRequestService private requestService: IRequestService + ) { this._filter = filter; this._remoteSearchP = filter ? this.getSettingsFromBing(filter, endpoint) : TPromise.wrap(null); } @@ -156,15 +170,22 @@ class RemoteSearchProvider { private getSettingsFromBing(filter: string, endpoint: IEndpointDetails): TPromise { const url = prepareUrl(filter, endpoint, this.environmentService.settingsSearchBuildId); const start = Date.now(); - const p = fetch(url, { - headers: new Headers({ + const p = this.requestService.request({ + url, + headers: { 'User-Agent': 'request', 'Content-Type': 'application/json; charset=utf-8', 'api-key': endpoint.key - }) + } }) - .then(r => r.json()) - .then(result => { + .then(context => { + if (context.res.statusCode >= 300) { + throw new Error(`${url} returned status code: ${context.res.statusCode}`); + } + + return asJson(context); + }) + .then((result: any) => { const timestamp = Date.now(); const duration = timestamp - start; const suggestions = (result.value || []) @@ -221,7 +242,7 @@ function prepareUrl(query: string, endpoint: IEndpointDetails, buildNumber: numb url += `&$filter startbuildno le ${buildNumber} and endbuildno ge ${buildNumber}`; } - return url + `&$filter=startbuildno le 119000227 and endbuildno ge 119000227`; + return url; } class SettingMatches { diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index 0efbcde5c55..454594c53e9 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -29,7 +29,7 @@ import 'vs/workbench/browser/actions/toggleSidebarPosition'; import 'vs/workbench/browser/actions/toggleEditorLayout'; import 'vs/workbench/browser/actions/toggleZenMode'; import 'vs/workbench/browser/actions/toggleTabsVisibility'; -import 'vs/workbench/parts/preferences/browser/preferences.contribution'; +import 'vs/workbench/parts/preferences/electron-browser/preferences.contribution'; import 'vs/workbench/parts/preferences/browser/keybindingsEditorContribution'; import 'vs/workbench/browser/parts/quickopen/quickopen.contribution';