mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 13:00:58 +00:00
Merge pull request #43274 from Microsoft/roblou/settingsSearchIssueReporter
Use issue reporter for settings search
This commit is contained in:
commit
540a998a46
|
@ -11,6 +11,7 @@ import { localize } from 'vs/nls';
|
|||
import { $ } from 'vs/base/browser/dom';
|
||||
import * as collections from 'vs/base/common/collections';
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
import { escape } from 'vs/base/common/strings';
|
||||
import product from 'vs/platform/node/product';
|
||||
import pkg from 'vs/platform/node/package';
|
||||
import * as os from 'os';
|
||||
|
@ -30,7 +31,7 @@ import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProper
|
|||
import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc';
|
||||
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { IssueReporterModel } from 'vs/code/electron-browser/issue/issueReporterModel';
|
||||
import { IssueReporterData, IssueReporterStyles, IssueType } from 'vs/platform/issue/common/issue';
|
||||
import { IssueReporterData, IssueReporterStyles, IssueType, ISettingsSearchIssueReporterData } from 'vs/platform/issue/common/issue';
|
||||
import BaseHtml from 'vs/code/electron-browser/issue/issueReporterPage';
|
||||
import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
|
@ -67,7 +68,8 @@ export class IssueReporter extends Disposable {
|
|||
includeSystemInfo: true,
|
||||
includeWorkspaceInfo: true,
|
||||
includeProcessInfo: true,
|
||||
includeExtensions: true,
|
||||
includeSearchedExtensions: true,
|
||||
includeSettingsSearchDetails: true,
|
||||
versionInfo: {
|
||||
vscodeVersion: `${pkg.name} ${pkg.version} (${product.commit || 'Commit unknown'}, ${product.date || 'Date unknown'})`,
|
||||
os: `${os.type()} ${os.arch()} ${os.release()}`
|
||||
|
@ -101,14 +103,18 @@ export class IssueReporter extends Disposable {
|
|||
show(document.getElementById('english'));
|
||||
}
|
||||
|
||||
this.setUpTypes();
|
||||
this.setEventHandlers();
|
||||
this.applyZoom(configuration.data.zoomLevel);
|
||||
this.applyStyles(configuration.data.styles);
|
||||
this.handleExtensionData(configuration.data.enabledExtensions);
|
||||
|
||||
if (configuration.data.issueType === IssueType.SettingsSearchIssue) {
|
||||
this.handleSettingsSearchData(<ISettingsSearchIssueReporterData>configuration.data);
|
||||
}
|
||||
}
|
||||
|
||||
render(): void {
|
||||
(<HTMLSelectElement>document.getElementById('issue-type')).value = this.issueReporterModel.getData().issueType.toString();
|
||||
this.renderBlocks();
|
||||
}
|
||||
|
||||
|
@ -203,6 +209,46 @@ export class IssueReporter extends Disposable {
|
|||
}
|
||||
}
|
||||
|
||||
private handleSettingsSearchData(data: ISettingsSearchIssueReporterData): void {
|
||||
this.issueReporterModel.update({
|
||||
actualSearchResults: data.actualSearchResults,
|
||||
query: data.query,
|
||||
filterResultCount: data.filterResultCount
|
||||
});
|
||||
this.updateSearchedExtensionTable(data.enabledExtensions);
|
||||
this.updateSettingsSearchDetails(data);
|
||||
}
|
||||
|
||||
private updateSettingsSearchDetails(data: ISettingsSearchIssueReporterData): void {
|
||||
const target = document.querySelector('.block-settingsSearchResults .block-info');
|
||||
|
||||
const details = `
|
||||
<div class='block-settingsSearchResults-details'>
|
||||
<div>Query: "${data.query}"</div>
|
||||
<div>Literal match count: ${data.filterResultCount}</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
let table = `
|
||||
<tr>
|
||||
<th>Setting</th>
|
||||
<th>Extension</th>
|
||||
<th>Score</th>
|
||||
</tr>`;
|
||||
|
||||
data.actualSearchResults
|
||||
.forEach(setting => {
|
||||
table += `
|
||||
<tr>
|
||||
<td>${setting.key}</td>
|
||||
<td>${setting.extensionId}</td>
|
||||
<td>${String(setting.score).slice(0, 5)}</td>
|
||||
</tr>`;
|
||||
});
|
||||
|
||||
target.innerHTML = `${details}<table>${table}</table>`;
|
||||
}
|
||||
|
||||
private initServices(configuration: IWindowConfiguration): void {
|
||||
const serviceCollection = new ServiceCollection();
|
||||
const mainProcessClient = new ElectronIPCClient(String(`window${configuration.windowId}`));
|
||||
|
@ -238,7 +284,7 @@ export class IssueReporter extends Disposable {
|
|||
this.render();
|
||||
});
|
||||
|
||||
['includeSystemInfo', 'includeProcessInfo', 'includeWorkspaceInfo', 'includeExtensions'].forEach(elementId => {
|
||||
['includeSystemInfo', 'includeProcessInfo', 'includeWorkspaceInfo', 'includeExtensions', 'includeSearchedExtensions', 'includeSettingsSearchDetails'].forEach(elementId => {
|
||||
document.getElementById(elementId).addEventListener('click', (event: Event) => {
|
||||
event.stopPropagation();
|
||||
this.issueReporterModel.update({ [elementId]: !this.issueReporterModel.getData()[elementId] });
|
||||
|
@ -351,6 +397,10 @@ export class IssueReporter extends Disposable {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (issueType === IssueType.SettingsSearchIssue) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -425,6 +475,25 @@ export class IssueReporter extends Disposable {
|
|||
this.telemetryService.publicLog('issueReporterSearchError', { message: error.message });
|
||||
}
|
||||
|
||||
private setUpTypes(): void {
|
||||
const makeOption = (issueType: IssueType, description: string) => `<option value="${issueType.valueOf()}">${escape(description)}</option>`;
|
||||
|
||||
const typeSelect = (<HTMLSelectElement>document.getElementById('issue-type'));
|
||||
const { issueType } = this.issueReporterModel.getData();
|
||||
if (issueType === IssueType.SettingsSearchIssue) {
|
||||
typeSelect.innerHTML = makeOption(IssueType.SettingsSearchIssue, localize('settingsSearchIssue', "Settings Search Issue"));
|
||||
typeSelect.disabled = true;
|
||||
} else {
|
||||
typeSelect.innerHTML = [
|
||||
makeOption(IssueType.Bug, localize('bugReporter', "Bug Report")),
|
||||
makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue")),
|
||||
makeOption(IssueType.FeatureRequest, localize('featureRequest', "Feature Request"))
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
typeSelect.value = issueType.toString();
|
||||
}
|
||||
|
||||
private renderBlocks(): void {
|
||||
// Depending on Issue Type, we render different blocks and text
|
||||
const { issueType } = this.issueReporterModel.getData();
|
||||
|
@ -432,16 +501,24 @@ export class IssueReporter extends Disposable {
|
|||
const processBlock = document.querySelector('.block-process');
|
||||
const workspaceBlock = document.querySelector('.block-workspace');
|
||||
const extensionsBlock = document.querySelector('.block-extensions');
|
||||
const disabledExtensions = document.getElementById('disabledExtensions');
|
||||
const searchedExtensionsBlock = document.querySelector('.block-searchedExtensions');
|
||||
const settingsSearchResultsBlock = document.querySelector('.block-settingsSearchResults');
|
||||
|
||||
const disabledExtensions = document.getElementById('disabledExtensions');
|
||||
const descriptionTitle = document.getElementById('issue-description-label');
|
||||
const descriptionSubtitle = document.getElementById('issue-description-subtitle');
|
||||
|
||||
// Hide all by default
|
||||
hide(systemBlock);
|
||||
hide(processBlock);
|
||||
hide(workspaceBlock);
|
||||
hide(extensionsBlock);
|
||||
hide(searchedExtensionsBlock);
|
||||
hide(settingsSearchResultsBlock);
|
||||
hide(disabledExtensions);
|
||||
|
||||
if (issueType === IssueType.Bug) {
|
||||
show(systemBlock);
|
||||
hide(processBlock);
|
||||
hide(workspaceBlock);
|
||||
show(extensionsBlock);
|
||||
show(disabledExtensions);
|
||||
|
||||
|
@ -456,15 +533,15 @@ export class IssueReporter extends Disposable {
|
|||
|
||||
descriptionTitle.innerHTML = `${localize('stepsToReproduce', "Steps to Reproduce")} <span class="required-input">*</span>`;
|
||||
descriptionSubtitle.innerHTML = localize('performanceIssueDesciption', "When did this performance issue happen? Does it occur on startup or after a specific series of actions? We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub.");
|
||||
} else {
|
||||
hide(systemBlock);
|
||||
hide(processBlock);
|
||||
hide(workspaceBlock);
|
||||
hide(extensionsBlock);
|
||||
hide(disabledExtensions);
|
||||
|
||||
} else if (issueType === IssueType.FeatureRequest) {
|
||||
descriptionTitle.innerHTML = `${localize('description', "Description")} <span class="required-input">*</span>`;
|
||||
descriptionSubtitle.innerHTML = localize('featureRequestDescription', "Please describe the feature you would like to see. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub.");
|
||||
} else if (issueType === IssueType.SettingsSearchIssue) {
|
||||
show(searchedExtensionsBlock);
|
||||
show(settingsSearchResultsBlock);
|
||||
|
||||
descriptionTitle.innerHTML = `${localize('expectedResults', "Expected Results")} <span class="required-input">*</span>`;
|
||||
descriptionSubtitle.innerHTML = localize('settingsSearchResultsDescription', "Please list the results that you were expecting to see when you searched with this query. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -591,6 +668,23 @@ export class IssueReporter extends Disposable {
|
|||
return;
|
||||
}
|
||||
|
||||
const table = this.getExtensionTableHtml(extensions);
|
||||
target.innerHTML = `<table>${table}</table>${themeExclusionStr}`;
|
||||
}
|
||||
|
||||
private updateSearchedExtensionTable(extensions: ILocalExtension[]): void {
|
||||
const target = document.querySelector('.block-searchedExtensions .block-info');
|
||||
|
||||
if (!extensions.length) {
|
||||
target.innerHTML = 'Extensions: none';
|
||||
return;
|
||||
}
|
||||
|
||||
const table = this.getExtensionTableHtml(extensions);
|
||||
target.innerHTML = `<table>${table}</table>`;
|
||||
}
|
||||
|
||||
private getExtensionTableHtml(extensions: ILocalExtension[]): string {
|
||||
let table = `
|
||||
<tr>
|
||||
<th>Extension</th>
|
||||
|
@ -598,16 +692,16 @@ export class IssueReporter extends Disposable {
|
|||
<th>Version</th>
|
||||
</tr>`;
|
||||
|
||||
extensions.forEach(extension => {
|
||||
table += `
|
||||
table += extensions.map(extension => {
|
||||
return `
|
||||
<tr>
|
||||
<td>${extension.manifest.name}</td>
|
||||
<td>${extension.manifest.publisher.substr(0, 3)}</td>
|
||||
<td>${extension.manifest.version}</td>
|
||||
</tr>`;
|
||||
});
|
||||
}).join('');
|
||||
|
||||
target.innerHTML = `<table>${table}</table>${themeExclusionStr}`;
|
||||
return table;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IssueType } from 'vs/platform/issue/common/issue';
|
||||
import { IssueType, ISettingSearchResult } from 'vs/platform/issue/common/issue';
|
||||
|
||||
export interface IssueReporterData {
|
||||
issueType?: IssueType;
|
||||
|
@ -22,11 +22,16 @@ export interface IssueReporterData {
|
|||
includeWorkspaceInfo?: boolean;
|
||||
includeProcessInfo?: boolean;
|
||||
includeExtensions?: boolean;
|
||||
includeSearchedExtensions?: boolean;
|
||||
includeSettingsSearchDetails?: boolean;
|
||||
|
||||
numberOfThemeExtesions?: number;
|
||||
enabledNonThemeExtesions?: ILocalExtension[];
|
||||
extensionsDisabled?: boolean;
|
||||
reprosWithoutExtensions?: boolean;
|
||||
actualSearchResults?: ISettingSearchResult[];
|
||||
query?: string;
|
||||
filterResultCount?: number;
|
||||
}
|
||||
|
||||
export class IssueReporterModel {
|
||||
|
@ -99,6 +104,17 @@ ${this.getInfos()}`;
|
|||
info += this._data.reprosWithoutExtensions ? '\nReproduces without extensions' : '\nReproduces only with extensions';
|
||||
}
|
||||
|
||||
if (this._data.issueType === IssueType.SettingsSearchIssue) {
|
||||
if (this._data.includeSearchedExtensions) {
|
||||
info += this.generateExtensionsMd();
|
||||
}
|
||||
|
||||
if (this._data.includeSettingsSearchDetails) {
|
||||
info += this.generateSettingSearchResultsMd();
|
||||
info += '\n' + this.generateSettingsSearchResultDetailsMd();
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -171,6 +187,35 @@ ${tableHeader}
|
|||
${table}
|
||||
${themeExclusionStr}
|
||||
|
||||
</details>`;
|
||||
}
|
||||
|
||||
private generateSettingsSearchResultDetailsMd(): string {
|
||||
return `
|
||||
Query: ${this._data.query}
|
||||
Literal matches: ${this._data.filterResultCount}`;
|
||||
}
|
||||
|
||||
private generateSettingSearchResultsMd(): string {
|
||||
if (!this._data.actualSearchResults) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!this._data.actualSearchResults.length) {
|
||||
return `No fuzzy results`;
|
||||
}
|
||||
|
||||
let tableHeader = `Setting|Extension|Score
|
||||
---|---|---`;
|
||||
const table = this._data.actualSearchResults.map(setting => {
|
||||
return `${setting.key}|${setting.extensionId}|${String(setting.score).slice(0, 5)}`;
|
||||
}).join('\n');
|
||||
|
||||
return `<details><summary>Results</summary>
|
||||
|
||||
${tableHeader}
|
||||
${table}
|
||||
|
||||
</details>`;
|
||||
}
|
||||
}
|
|
@ -15,9 +15,7 @@ export default (): string => `
|
|||
<div class="input-group">
|
||||
<label id="issue-type-label" class="inline-form-control" for="issue-type">${escape(localize('issueTypeLabel', "This is a"))}</label>
|
||||
<select id="issue-type" class="inline-form-control">
|
||||
<option value="0">${escape(localize('bugReporter', "Bug Report"))}</option>
|
||||
<option value="1">${escape(localize('performanceIssue', "Performance Issue"))}</option>
|
||||
<option value="2">${escape(localize('featureRequest', "Feature Request"))}</option>
|
||||
<!-- To be dynamically filled -->
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
@ -86,6 +84,32 @@ export default (): string => `
|
|||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<div class="block block-searchedExtensions">
|
||||
<details>
|
||||
<summary>${escape(localize('searchedExtensions', "Searched Extensions"))}
|
||||
<div class="include-data">
|
||||
<input class="sendData" type="checkbox" id="includeSearchedExtensions" checked/>
|
||||
<label class="caption" for="includeSearchedExtensions">${escape(localize('sendData', "Send my data"))}</label>
|
||||
</div>
|
||||
</summary>
|
||||
<div class="block-info">
|
||||
<!-- To be dynamically filled -->
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<div class="block block-settingsSearchResults">
|
||||
<details>
|
||||
<summary>${escape(localize('settingsSearchDetails', "Settings Search Details"))}
|
||||
<div class="include-data">
|
||||
<input class="sendData" type="checkbox" id="includeSettingsSearchDetails" checked/>
|
||||
<label class="caption" for="includeSettingsSearchDetails">${escape(localize('sendData', "Send my data"))}</label>
|
||||
</div>
|
||||
</summary>
|
||||
<div class="block-info">
|
||||
<!-- To be dynamically filled -->
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -30,6 +30,14 @@ td {
|
|||
border-top: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
.block-settingsSearchResults-details {
|
||||
padding-bottom: .5rem;
|
||||
}
|
||||
|
||||
.block-settingsSearchResults-details > div {
|
||||
padding: .5rem .75rem;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
|
|
@ -9,13 +9,13 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
|||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
|
||||
export const ID = 'issueService';
|
||||
export const IIssueService = createDecorator<IIssueService>(ID);
|
||||
export const IIssueService = createDecorator<IIssueService>('issueService');
|
||||
|
||||
export enum IssueType {
|
||||
Bug,
|
||||
PerformanceIssue,
|
||||
FeatureRequest
|
||||
FeatureRequest,
|
||||
SettingsSearchIssue
|
||||
}
|
||||
|
||||
export interface IssueReporterStyles {
|
||||
|
@ -42,7 +42,20 @@ export interface IssueReporterData {
|
|||
issueType?: IssueType;
|
||||
}
|
||||
|
||||
export interface ISettingSearchResult {
|
||||
extensionId: string;
|
||||
key: string;
|
||||
score: number;
|
||||
}
|
||||
|
||||
export interface ISettingsSearchIssueReporterData extends IssueReporterData {
|
||||
issueType: IssueType.SettingsSearchIssue;
|
||||
actualSearchResults: ISettingSearchResult[];
|
||||
query: string;
|
||||
filterResultCount: number;
|
||||
}
|
||||
|
||||
export interface IIssueService {
|
||||
_serviceBrand: any;
|
||||
openReporter(data: IssueReporterData): TPromise<void>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import { IMessageService, Severity } from 'vs/platform/message/common/message';
|
|||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { IExtensionManagementService, LocalExtensionType, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import paths = require('vs/base/common/paths');
|
||||
import { isMacintosh, isLinux } from 'vs/base/common/platform';
|
||||
|
@ -44,17 +43,14 @@ import { FileKind } from 'vs/platform/files/common/files';
|
|||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtensionService, ActivationTimes } from 'vs/platform/extensions/common/extensions';
|
||||
import { getEntries } from 'vs/base/common/performance';
|
||||
import { IIssueService, IssueReporterData, IssueType, IssueReporterStyles } from 'vs/platform/issue/common/issue';
|
||||
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
||||
import { textLinkForeground, inputBackground, inputBorder, inputForeground, buttonBackground, buttonHoverBackground, buttonForeground, inputValidationErrorBorder, foreground, inputActiveOptionBorder, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { getGalleryExtensionIdFromLocal } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IssueType } from 'vs/platform/issue/common/issue';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { once } from 'vs/base/common/event';
|
||||
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { getDomNodePagePosition, createStyleSheet, createCSSRule } from 'vs/base/browser/dom';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { Context } from 'vs/platform/contextkey/browser/contextKeyService';
|
||||
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
|
||||
|
||||
// --- actions
|
||||
|
||||
|
@ -869,25 +865,6 @@ export class CloseMessagesAction extends Action {
|
|||
}
|
||||
}
|
||||
|
||||
export function getIssueReporterStyles(theme: ITheme): IssueReporterStyles {
|
||||
return {
|
||||
backgroundColor: theme.getColor(SIDE_BAR_BACKGROUND) && theme.getColor(SIDE_BAR_BACKGROUND).toString(),
|
||||
color: theme.getColor(foreground).toString(),
|
||||
textLinkColor: theme.getColor(textLinkForeground) && theme.getColor(textLinkForeground).toString(),
|
||||
inputBackground: theme.getColor(inputBackground) && theme.getColor(inputBackground).toString(),
|
||||
inputForeground: theme.getColor(inputForeground) && theme.getColor(inputForeground).toString(),
|
||||
inputBorder: theme.getColor(inputBorder) && theme.getColor(inputBorder).toString(),
|
||||
inputActiveBorder: theme.getColor(inputActiveOptionBorder) && theme.getColor(inputActiveOptionBorder).toString(),
|
||||
inputErrorBorder: theme.getColor(inputValidationErrorBorder) && theme.getColor(inputValidationErrorBorder).toString(),
|
||||
buttonBackground: theme.getColor(buttonBackground) && theme.getColor(buttonBackground).toString(),
|
||||
buttonForeground: theme.getColor(buttonForeground) && theme.getColor(buttonForeground).toString(),
|
||||
buttonHoverBackground: theme.getColor(buttonHoverBackground) && theme.getColor(buttonHoverBackground).toString(),
|
||||
sliderActiveColor: theme.getColor(scrollbarSliderActiveBackground) && theme.getColor(scrollbarSliderActiveBackground).toString(),
|
||||
sliderBackgroundColor: theme.getColor(scrollbarSliderBackground) && theme.getColor(scrollbarSliderBackground).toString(),
|
||||
sliderHoverColor: theme.getColor(scrollbarSliderHoverBackground) && theme.getColor(scrollbarSliderHoverBackground).toString()
|
||||
};
|
||||
}
|
||||
|
||||
export class OpenIssueReporterAction extends Action {
|
||||
public static readonly ID = 'workbench.action.openIssueReporter';
|
||||
public static readonly LABEL = nls.localize({ key: 'reportIssueInEnglish', comment: ['Translate this to "Report Issue in English" in all languages please!'] }, "Report Issue");
|
||||
|
@ -895,28 +872,14 @@ export class OpenIssueReporterAction extends Action {
|
|||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IIssueService private issueService: IIssueService,
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@IExtensionManagementService private extensionManagementService: IExtensionManagementService,
|
||||
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService
|
||||
@IWorkbenchIssueService private issueService: IWorkbenchIssueService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
public run(): TPromise<boolean> {
|
||||
return this.extensionManagementService.getInstalled(LocalExtensionType.User).then(extensions => {
|
||||
const enabledExtensions = extensions.filter(extension => this.extensionEnablementService.isEnabled({ id: getGalleryExtensionIdFromLocal(extension) }));
|
||||
const theme = this.themeService.getTheme();
|
||||
const issueReporterData: IssueReporterData = {
|
||||
styles: getIssueReporterStyles(theme),
|
||||
zoomLevel: webFrame.getZoomLevel(),
|
||||
enabledExtensions
|
||||
};
|
||||
|
||||
return this.issueService.openReporter(issueReporterData).then(() => {
|
||||
return TPromise.as(true);
|
||||
});
|
||||
});
|
||||
return this.issueService.openReporter()
|
||||
.then(() => true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -927,30 +890,15 @@ export class ReportPerformanceIssueUsingReporterAction extends Action {
|
|||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IIssueService private issueService: IIssueService,
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@IExtensionManagementService private extensionManagementService: IExtensionManagementService,
|
||||
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService
|
||||
@IWorkbenchIssueService private issueService: IWorkbenchIssueService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
public run(): TPromise<boolean> {
|
||||
return this.extensionManagementService.getInstalled(LocalExtensionType.User).then(extensions => {
|
||||
const enabledExtensions = extensions.filter(extension => this.extensionEnablementService.isEnabled(extension.identifier));
|
||||
const theme = this.themeService.getTheme();
|
||||
const issueReporterData: IssueReporterData = {
|
||||
styles: getIssueReporterStyles(theme),
|
||||
zoomLevel: webFrame.getZoomLevel(),
|
||||
enabledExtensions,
|
||||
issueType: IssueType.PerformanceIssue
|
||||
};
|
||||
|
||||
// TODO: Reporter should send timings table as well
|
||||
return this.issueService.openReporter(issueReporterData).then(() => {
|
||||
return TPromise.as(true);
|
||||
});
|
||||
});
|
||||
// TODO: Reporter should send timings table as well
|
||||
return this.issueService.openReporter({ issueType: IssueType.PerformanceIssue })
|
||||
.then(() => true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -92,6 +92,8 @@ import { stat } from 'fs';
|
|||
import { join } from 'path';
|
||||
import { ILocalizationsChannel, LocalizationsChannelClient } from 'vs/platform/localizations/common/localizationsIpc';
|
||||
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
|
||||
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
|
||||
import { WorkbenchIssueService } from 'vs/workbench/services/issue/electron-browser/workbenchIssueService';
|
||||
|
||||
/**
|
||||
* Services that we require for the Shell
|
||||
|
@ -445,6 +447,8 @@ export class WorkbenchShell {
|
|||
|
||||
serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
|
||||
|
||||
serviceCollection.set(IWorkbenchIssueService, new SyncDescriptor(WorkbenchIssueService));
|
||||
|
||||
serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
|
||||
|
||||
serviceCollection.set(IIntegrityService, new SyncDescriptor(IntegrityServiceImpl));
|
||||
|
|
|
@ -18,7 +18,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
|
|||
import { Range, IRange } from 'vs/editor/common/core/range';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IPreferencesService, ISettingsGroup, ISetting, IPreferencesEditorModel, IFilterResult, ISettingsEditorModel, IScoredResults, IWorkbenchSettingsConfiguration, IExtensionSetting } from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { IPreferencesService, ISettingsGroup, ISetting, IPreferencesEditorModel, IFilterResult, ISettingsEditorModel, IWorkbenchSettingsConfiguration, IExtensionSetting, IScoredResults } from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { SettingsEditorModel, DefaultSettingsEditorModel, WorkspaceConfigurationEditorModel } from 'vs/workbench/parts/preferences/common/preferencesModels';
|
||||
import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
|
||||
import { IContextMenuService, ContextSubMenu } from 'vs/platform/contextview/browser/contextView';
|
||||
|
@ -26,8 +26,7 @@ import { SettingsGroupTitleWidget, EditPreferenceWidget, SettingsHeaderWidget, D
|
|||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { RangeHighlightDecorations } from 'vs/workbench/browser/parts/editor/rangeDecorations';
|
||||
import { IMarkerService, IMarkerData } from 'vs/platform/markers/common/markers';
|
||||
import { IMessageService, Severity } from 'vs/platform/message/common/message';
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { Severity, IMessageService } from 'vs/platform/message/common/message';
|
||||
import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
|
||||
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
|
@ -38,6 +37,10 @@ import { ITextModel, IModelDeltaDecoration, TrackedRangeStickiness } from 'vs/ed
|
|||
import { CodeLensProviderRegistry, CodeLensProvider, ICodeLensSymbol } from 'vs/editor/common/modes';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { getDomNodePagePosition } from 'vs/base/browser/dom';
|
||||
import { IssueType, ISettingsSearchIssueReporterData, ISettingSearchResult } from 'vs/platform/issue/common/issue';
|
||||
import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
||||
export interface IPreferencesRenderer<T> extends IDisposable {
|
||||
readonly preferencesModel: IPreferencesEditorModel<T>;
|
||||
|
@ -247,6 +250,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
|
|||
private filteredMatchesRenderer: FilteredMatchesRenderer;
|
||||
private hiddenAreasRenderer: HiddenAreasRenderer;
|
||||
private editSettingActionRenderer: EditSettingRenderer;
|
||||
private issueWidgetRenderer: IssueWidgetRenderer;
|
||||
private feedbackWidgetRenderer: FeedbackWidgetRenderer;
|
||||
private bracesHidingRenderer: BracesHidingRenderer;
|
||||
private extensionCodelensRenderer: ExtensionCodelensRenderer;
|
||||
|
@ -263,7 +267,8 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
|
|||
|
||||
constructor(protected editor: ICodeEditor, public readonly preferencesModel: DefaultSettingsEditorModel,
|
||||
@IPreferencesService protected preferencesService: IPreferencesService,
|
||||
@IInstantiationService protected instantiationService: IInstantiationService
|
||||
@IInstantiationService protected instantiationService: IInstantiationService,
|
||||
@IConfigurationService private configurationService: IConfigurationService
|
||||
) {
|
||||
super();
|
||||
this.settingHighlighter = this._register(instantiationService.createInstance(SettingHighlighter, editor, this._onFocusPreference, this._onClearFocusPreference));
|
||||
|
@ -271,6 +276,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
|
|||
this.settingsGroupTitleRenderer = this._register(instantiationService.createInstance(SettingsGroupTitleRenderer, editor));
|
||||
this.filteredMatchesRenderer = this._register(instantiationService.createInstance(FilteredMatchesRenderer, editor));
|
||||
this.editSettingActionRenderer = this._register(instantiationService.createInstance(EditSettingRenderer, editor, preferencesModel, this.settingHighlighter));
|
||||
this.issueWidgetRenderer = this._register(instantiationService.createInstance(IssueWidgetRenderer, editor));
|
||||
this.feedbackWidgetRenderer = this._register(instantiationService.createInstance(FeedbackWidgetRenderer, editor));
|
||||
this.bracesHidingRenderer = this._register(instantiationService.createInstance(BracesHidingRenderer, editor, preferencesModel));
|
||||
this.hiddenAreasRenderer = this._register(instantiationService.createInstance(HiddenAreasRenderer, editor, [this.settingsGroupTitleRenderer, this.filteredMatchesRenderer, this.bracesHidingRenderer]));
|
||||
|
@ -293,6 +299,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
|
|||
public render() {
|
||||
this.settingsGroupTitleRenderer.render(this.preferencesModel.settingsGroups);
|
||||
this.editSettingActionRenderer.render(this.preferencesModel.settingsGroups, this._associatedPreferencesModel);
|
||||
this.issueWidgetRenderer.render(null);
|
||||
this.feedbackWidgetRenderer.render(null);
|
||||
this.settingHighlighter.clear(true);
|
||||
this.bracesHidingRenderer.render(null, this.preferencesModel.settingsGroups);
|
||||
|
@ -306,7 +313,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
|
|||
if (filterResult) {
|
||||
this.filteredMatchesRenderer.render(filterResult, this.preferencesModel.settingsGroups);
|
||||
this.settingsGroupTitleRenderer.render(null);
|
||||
this.feedbackWidgetRenderer.render(filterResult);
|
||||
this.renderIssueWidget(filterResult);
|
||||
this.settingsHeaderRenderer.render(filterResult);
|
||||
this.settingHighlighter.clear(true);
|
||||
this.bracesHidingRenderer.render(filterResult, this.preferencesModel.settingsGroups);
|
||||
|
@ -315,7 +322,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
|
|||
} else {
|
||||
this.settingHighlighter.clear(true);
|
||||
this.filteredMatchesRenderer.render(null, this.preferencesModel.settingsGroups);
|
||||
this.feedbackWidgetRenderer.render(null);
|
||||
this.renderIssueWidget(null);
|
||||
this.settingsHeaderRenderer.render(null);
|
||||
this.settingsGroupTitleRenderer.render(this.preferencesModel.settingsGroups);
|
||||
this.settingsGroupTitleRenderer.showGroup(0);
|
||||
|
@ -327,6 +334,17 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
|
|||
this.hiddenAreasRenderer.render();
|
||||
}
|
||||
|
||||
private renderIssueWidget(filterResult: IFilterResult): void {
|
||||
const workbenchSettings = this.configurationService.getValue<IWorkbenchSettingsConfiguration>().workbench.settings;
|
||||
if (workbenchSettings.enableNaturalLanguageSearchFeedback) {
|
||||
this.issueWidgetRenderer.render(null);
|
||||
this.feedbackWidgetRenderer.render(filterResult);
|
||||
} else {
|
||||
this.feedbackWidgetRenderer.render(null);
|
||||
this.issueWidgetRenderer.render(filterResult);
|
||||
}
|
||||
}
|
||||
|
||||
public focusPreference(s: ISetting): void {
|
||||
const setting = this.getSetting(s);
|
||||
if (setting) {
|
||||
|
@ -594,9 +612,8 @@ export class FeedbackWidgetRenderer extends Disposable {
|
|||
}
|
||||
|
||||
public render(result: IFilterResult): void {
|
||||
const workbenchSettings = this.configurationService.getValue<IWorkbenchSettingsConfiguration>().workbench.settings;
|
||||
this._currentResult = result;
|
||||
if (result && result.metadata && workbenchSettings.enableNaturalLanguageSearchFeedback) {
|
||||
if (result && result.metadata) {
|
||||
this.showWidget();
|
||||
} else if (this._feedbackWidget) {
|
||||
this.disposeWidget();
|
||||
|
@ -762,7 +779,88 @@ export class FeedbackWidgetRenderer extends Disposable {
|
|||
|
||||
public dispose() {
|
||||
this.disposeWidget();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export class IssueWidgetRenderer extends Disposable {
|
||||
private _issueWidget: FloatingClickWidget;
|
||||
private _currentResult: IFilterResult;
|
||||
|
||||
constructor(private editor: ICodeEditor,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IWorkbenchIssueService private issueService: IWorkbenchIssueService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
public render(result: IFilterResult): void {
|
||||
this._currentResult = result;
|
||||
if (result && result.metadata && this.environmentService.appQuality !== 'stable') {
|
||||
this.showWidget();
|
||||
} else if (this._issueWidget) {
|
||||
this.disposeWidget();
|
||||
}
|
||||
}
|
||||
|
||||
private showWidget(): void {
|
||||
if (!this._issueWidget) {
|
||||
this._issueWidget = this._register(this.instantiationService.createInstance(FloatingClickWidget, this.editor, nls.localize('reportSettingsSearchIssue', "Report Issue"), null));
|
||||
this._register(this._issueWidget.onClick(() => this.showIssueReporter()));
|
||||
this._issueWidget.render();
|
||||
}
|
||||
}
|
||||
|
||||
private showIssueReporter(): TPromise<void> {
|
||||
const nlpMetadata = this._currentResult.metadata['nlpResult'];
|
||||
const results = nlpMetadata.scoredResults;
|
||||
|
||||
const enabledExtensions = nlpMetadata.extensions;
|
||||
const issueResults = Object.keys(results)
|
||||
.map(key => (<ISettingSearchResult>{
|
||||
key: key.split('##')[1],
|
||||
extensionId: results[key].packageId === 'core' ?
|
||||
'core' :
|
||||
this.getExtensionIdByGuid(enabledExtensions, results[key].packageId),
|
||||
score: results[key].score
|
||||
}))
|
||||
.slice(0, 20);
|
||||
|
||||
const issueReporterData: Partial<ISettingsSearchIssueReporterData> = {
|
||||
enabledExtensions,
|
||||
issueType: IssueType.SettingsSearchIssue,
|
||||
actualSearchResults: issueResults,
|
||||
filterResultCount: this.getFilterResultCount(),
|
||||
query: this._currentResult.query
|
||||
};
|
||||
|
||||
return this.issueService.openReporter(issueReporterData);
|
||||
}
|
||||
|
||||
private getFilterResultCount(): number {
|
||||
const filterResultGroup = arrays.first(this._currentResult.filteredGroups, group => group.id === 'filterResult');
|
||||
return filterResultGroup ?
|
||||
filterResultGroup.sections[0].settings.length :
|
||||
0;
|
||||
}
|
||||
|
||||
private getExtensionIdByGuid(extensions: ILocalExtension[], guid: string): string {
|
||||
const match = arrays.first(extensions, ext => ext.identifier.uuid === guid);
|
||||
|
||||
// identifier.id includes the version, not needed here
|
||||
return match && `${match.manifest.publisher}.${match.manifest.name}`;
|
||||
}
|
||||
|
||||
private disposeWidget(): void {
|
||||
if (this._issueWidget) {
|
||||
this._issueWidget.dispose();
|
||||
this._issueWidget = null;
|
||||
}
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this.disposeWidget();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import { join } from 'vs/base/common/paths';
|
|||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import Event from 'vs/base/common/event';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
|
||||
export interface IWorkbenchSettingsConfiguration {
|
||||
workbench: {
|
||||
|
@ -110,6 +111,9 @@ export interface IFilterMetadata {
|
|||
timestamp: number;
|
||||
duration: number;
|
||||
scoredResults: IScoredResults;
|
||||
extensions?: ILocalExtension[];
|
||||
|
||||
/** The number of requests made, since requests are split by number of filters */
|
||||
requestCount?: number;
|
||||
|
||||
/** The name of the server that actually served the request */
|
||||
|
|
|
@ -42,8 +42,10 @@ export class PreferencesSearchService extends Disposable implements IPreferences
|
|||
|
||||
// This request goes to the shared process but results won't change during a window's lifetime, so cache the results.
|
||||
this._installedExtensions = this.extensionManagementService.getInstalled(LocalExtensionType.User).then(exts => {
|
||||
// Filter to enabled extensions
|
||||
return exts.filter(ext => this.extensionEnablementService.isEnabled(ext.identifier));
|
||||
// Filter to enabled extensions that have settings
|
||||
return exts
|
||||
.filter(ext => this.extensionEnablementService.isEnabled(ext.identifier))
|
||||
.filter(ext => ext.manifest.contributes && ext.manifest.contributes.configuration);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -132,6 +134,7 @@ interface IBingRequestDetails {
|
|||
url: string;
|
||||
body?: string;
|
||||
hasMoreFilters?: boolean;
|
||||
extensions?: ILocalExtension[];
|
||||
}
|
||||
|
||||
class RemoteSearchProvider implements ISearchProvider {
|
||||
|
@ -280,7 +283,8 @@ class RemoteSearchProvider implements ISearchProvider {
|
|||
duration,
|
||||
timestamp,
|
||||
scoredResults,
|
||||
context: result['@odata.context']
|
||||
context: result['@odata.context'],
|
||||
extensions: details.extensions
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -315,9 +319,10 @@ class RemoteSearchProvider implements ISearchProvider {
|
|||
url += `${API_VERSION}&${QUERY_TYPE}`;
|
||||
}
|
||||
|
||||
const extensions = await this.installedExtensions;
|
||||
const filters = this.options.newExtensionsOnly ?
|
||||
[`diminish eq 'latest'`] :
|
||||
await this.getVersionFilters(this.environmentService.settingsSearchBuildId);
|
||||
this.getVersionFilters(extensions, this.environmentService.settingsSearchBuildId);
|
||||
|
||||
const filterStr = filters
|
||||
.slice(filterPage * RemoteSearchProvider.MAX_REQUEST_FILTERS, (filterPage + 1) * RemoteSearchProvider.MAX_REQUEST_FILTERS)
|
||||
|
@ -333,23 +338,22 @@ class RemoteSearchProvider implements ISearchProvider {
|
|||
return {
|
||||
url,
|
||||
body,
|
||||
hasMoreFilters
|
||||
hasMoreFilters,
|
||||
extensions
|
||||
};
|
||||
}
|
||||
|
||||
private getVersionFilters(buildNumber?: number): TPromise<string[]> {
|
||||
return this.installedExtensions.then(exts => {
|
||||
// Only search extensions that contribute settings
|
||||
const filters = exts
|
||||
.filter(ext => ext.manifest.contributes && ext.manifest.contributes.configuration)
|
||||
.map(ext => this.getExtensionFilter(ext));
|
||||
private getVersionFilters(exts: ILocalExtension[], buildNumber?: number): string[] {
|
||||
// Only search extensions that contribute settings
|
||||
const filters = exts
|
||||
.filter(ext => ext.manifest.contributes && ext.manifest.contributes.configuration)
|
||||
.map(ext => this.getExtensionFilter(ext));
|
||||
|
||||
if (buildNumber) {
|
||||
filters.push(`(packageid eq 'core' and startbuildno le '${buildNumber}' and endbuildno ge '${buildNumber}')`);
|
||||
}
|
||||
if (buildNumber) {
|
||||
filters.push(`(packageid eq 'core' and startbuildno le '${buildNumber}' and endbuildno ge '${buildNumber}')`);
|
||||
}
|
||||
|
||||
return filters;
|
||||
});
|
||||
return filters;
|
||||
}
|
||||
|
||||
private getExtensionFilter(ext: ILocalExtension): string {
|
||||
|
|
17
src/vs/workbench/services/issue/common/issue.ts
Normal file
17
src/vs/workbench/services/issue/common/issue.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IssueReporterData } from 'vs/platform/issue/common/issue';
|
||||
|
||||
export const IWorkbenchIssueService = createDecorator<IWorkbenchIssueService>('workbenchIssueService');
|
||||
|
||||
export interface IWorkbenchIssueService {
|
||||
_serviceBrand: any;
|
||||
openReporter(dataOverrides?: Partial<IssueReporterData>): TPromise<void>;
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { IssueReporterStyles, IIssueService, IssueReporterData } from 'vs/platform/issue/common/issue';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { textLinkForeground, inputBackground, inputBorder, inputForeground, buttonBackground, buttonHoverBackground, buttonForeground, inputValidationErrorBorder, foreground, inputActiveOptionBorder, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { IExtensionManagementService, IExtensionEnablementService, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { getGalleryExtensionIdFromLocal } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { webFrame } from 'electron';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
|
||||
|
||||
export class WorkbenchIssueService implements IWorkbenchIssueService {
|
||||
_serviceBrand: any;
|
||||
|
||||
constructor(
|
||||
@IIssueService private issueService: IIssueService,
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@IExtensionManagementService private extensionManagementService: IExtensionManagementService,
|
||||
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService
|
||||
) {
|
||||
}
|
||||
|
||||
openReporter(dataOverrides: Partial<IssueReporterData> = {}): TPromise<void> {
|
||||
return this.extensionManagementService.getInstalled(LocalExtensionType.User).then(extensions => {
|
||||
const enabledExtensions = extensions.filter(extension => this.extensionEnablementService.isEnabled({ id: getGalleryExtensionIdFromLocal(extension) }));
|
||||
const theme = this.themeService.getTheme();
|
||||
const issueReporterData: IssueReporterData = assign(
|
||||
{
|
||||
styles: getIssueReporterStyles(theme),
|
||||
zoomLevel: webFrame.getZoomLevel(),
|
||||
enabledExtensions
|
||||
},
|
||||
dataOverrides);
|
||||
|
||||
return this.issueService.openReporter(issueReporterData);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getIssueReporterStyles(theme: ITheme): IssueReporterStyles {
|
||||
return {
|
||||
backgroundColor: theme.getColor(SIDE_BAR_BACKGROUND) && theme.getColor(SIDE_BAR_BACKGROUND).toString(),
|
||||
color: theme.getColor(foreground).toString(),
|
||||
textLinkColor: theme.getColor(textLinkForeground) && theme.getColor(textLinkForeground).toString(),
|
||||
inputBackground: theme.getColor(inputBackground) && theme.getColor(inputBackground).toString(),
|
||||
inputForeground: theme.getColor(inputForeground) && theme.getColor(inputForeground).toString(),
|
||||
inputBorder: theme.getColor(inputBorder) && theme.getColor(inputBorder).toString(),
|
||||
inputActiveBorder: theme.getColor(inputActiveOptionBorder) && theme.getColor(inputActiveOptionBorder).toString(),
|
||||
inputErrorBorder: theme.getColor(inputValidationErrorBorder) && theme.getColor(inputValidationErrorBorder).toString(),
|
||||
buttonBackground: theme.getColor(buttonBackground) && theme.getColor(buttonBackground).toString(),
|
||||
buttonForeground: theme.getColor(buttonForeground) && theme.getColor(buttonForeground).toString(),
|
||||
buttonHoverBackground: theme.getColor(buttonHoverBackground) && theme.getColor(buttonHoverBackground).toString(),
|
||||
sliderActiveColor: theme.getColor(scrollbarSliderActiveBackground) && theme.getColor(scrollbarSliderActiveBackground).toString(),
|
||||
sliderBackgroundColor: theme.getColor(scrollbarSliderBackground) && theme.getColor(scrollbarSliderBackground).toString(),
|
||||
sliderHoverColor: theme.getColor(scrollbarSliderHoverBackground) && theme.getColor(scrollbarSliderHoverBackground).toString()
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue