web reporter refactor and issueFormService (#212951)

* web version working

* change to mainWindow

* PROPER MOVEMENT

* working for web as well

* move issueFormService to workbench/contrib/issue

* cleaning up{

* more cleanup, added setting

* styling

* use mainwindow to open and closee

* css fixes

* fix css again

* fix CSS and wonky applyCSS rules

* change gulpfile

* add and update system info

* address some of the comments

* move files! small changes

* move JS and non window specific back to electron sandbox

* fix on issueReporter.js

* fix build file

* fix gulp file too....

* move everything into contrib

* fix workbench import

* move everything else into contrib, fix import

* change name to web

* applying more feedback fixes :D

* fix command and remove unused import:

* add back issueTroubleshoot

* fix gulpile outputs

* fix out exclusion:
This commit is contained in:
Justin Chen 2024-05-24 11:36:46 -07:00 committed by GitHub
parent 0d350085d6
commit d05d280364
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 949 additions and 121 deletions

View file

@ -73,6 +73,8 @@ const vscodeResources = [
'out-build/vs/workbench/contrib/terminal/browser/media/*.sh',
'out-build/vs/workbench/contrib/terminal/browser/media/*.zsh',
'out-build/vs/workbench/contrib/webview/browser/pre/*.js',
'!out-build/vs/workbench/contrib/issue/browser/*.html',
'!out-build/vs/workbench/contrib/issue/**/*-dev.html',
'out-build/vs/**/markdown.css',
'out-build/vs/workbench/contrib/tasks/**/*.json',
'!**/test/**'
@ -122,7 +124,8 @@ const optimizeVSCodeTask = task.define('optimize-vscode', task.series(
},
manual: [
{ src: [...windowBootstrapFiles, 'out-build/vs/code/electron-sandbox/workbench/workbench.js'], out: 'vs/code/electron-sandbox/workbench/workbench.js' },
{ src: [...windowBootstrapFiles, 'out-build/vs/code/electron-sandbox/issue/issueReporter.js'], out: 'vs/code/electron-sandbox/issue/issueReporter.js' },
// TODO: @justchen https://github.com/microsoft/vscode/issues/213332 make sure to remove when we use window.open on desktop.
{ src: [...windowBootstrapFiles, 'out-build/vs/workbench/contrib/issue/electron-sandbox/issueReporter.js'], out: 'vs/workbench/contrib/issue/electron-sandbox/issueReporter.js' },
{ src: [...windowBootstrapFiles, 'out-build/vs/code/electron-sandbox/processExplorer/processExplorer.js'], out: 'vs/code/electron-sandbox/processExplorer/processExplorer.js' }
]
}

View file

@ -57,7 +57,8 @@ exports.workbenchDesktop = [
createModuleDescription('vs/workbench/contrib/debug/node/telemetryApp'),
createModuleDescription('vs/platform/files/node/watcher/watcherMain'),
createModuleDescription('vs/platform/terminal/node/ptyHostMain'),
createModuleDescription('vs/workbench/api/node/extensionHostProcess')
createModuleDescription('vs/workbench/api/node/extensionHostProcess'),
createModuleDescription('vs/workbench/contrib/issue/electron-sandbox/issueReporterMain'),
];
exports.workbenchWeb = [
@ -76,7 +77,6 @@ exports.code = [
createModuleDescription('vs/code/electron-main/main'),
createModuleDescription('vs/code/node/cli'),
createModuleDescription('vs/code/node/cliProcessMain', ['vs/code/node/cli']),
createModuleDescription('vs/code/electron-sandbox/issue/issueReporterMain'),
createModuleDescription('vs/code/node/sharedProcess/sharedProcessMain'),
createModuleDescription('vs/code/electron-sandbox/processExplorer/processExplorerMain')
];

View file

@ -173,7 +173,7 @@ export class IssueMainService implements IIssueMainService {
});
this.issueReporterWindow.loadURL(
FileAccess.asBrowserUri(`vs/code/electron-sandbox/issue/issueReporter${this.environmentMainService.isBuilt ? '' : '-dev'}.html`).toString(true)
FileAccess.asBrowserUri(`vs/workbench/contrib/issue/electron-sandbox/issueReporter${this.environmentMainService.isBuilt ? '' : '-dev'}.html`).toString(true)
);
this.issueReporterWindow.on('close', () => {

View file

@ -6,7 +6,7 @@
import * as nls from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/common/issue';
export class ReportExtensionIssueAction extends Action {

View file

@ -10,10 +10,14 @@ import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle
import { IProductService } from 'vs/platform/product/common/productService';
import { Registry } from 'vs/platform/registry/common/platform';
import { Extensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { WebIssueService } from 'vs/workbench/services/issue/browser/issueService';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
import { BrowserIssueService } from 'vs/workbench/contrib/issue/browser/issueService';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/common/issue';
import { BaseIssueContribution } from 'vs/workbench/contrib/issue/common/issue.contribution';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { IIssueMainService } from 'vs/platform/issue/common/issue';
import { IssueFormService } from 'vs/workbench/contrib/issue/browser/issueFormService';
import 'vs/workbench/contrib/issue/browser/issueTroubleshoot';
class WebIssueContribution extends BaseIssueContribution {
@ -24,8 +28,20 @@ class WebIssueContribution extends BaseIssueContribution {
Registry.as<IWorkbenchContributionsRegistry>(Extensions.Workbench).registerWorkbenchContribution(WebIssueContribution, LifecyclePhase.Restored);
registerSingleton(IWorkbenchIssueService, WebIssueService, InstantiationType.Delayed);
registerSingleton(IWorkbenchIssueService, BrowserIssueService, InstantiationType.Delayed);
registerSingleton(IIssueMainService, IssueFormService, InstantiationType.Delayed);
CommandsRegistry.registerCommand('_issues.getSystemStatus', (accessor) => {
return nls.localize('statusUnsupported', "The --status argument is not yet supported in browsers.");
});
Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
.registerConfiguration({
properties: {
'issueReporter.experimental.webReporter': {
type: 'boolean',
default: true,
description: 'Enable experimental issue reporter for web.',
},
}
});

View file

@ -14,11 +14,12 @@ import { CancellationError } from 'vs/base/common/errors';
import { isLinuxSnap } from 'vs/base/common/platform';
import { escape } from 'vs/base/common/strings';
import { URI } from 'vs/base/common/uri';
import { IssueReporterModel, IssueReporterData as IssueReporterModelData } from 'vs/code/browser/issue/issueReporterModel';
import { localize } from 'vs/nls';
import { IIssueMainService, IssueReporterData, IssueReporterExtensionData, IssueReporterStyles, IssueType } from 'vs/platform/issue/common/issue';
import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil';
import { getIconsStyleSheet } from 'vs/platform/theme/browser/iconsStyleSheet';
import { IssueReporterModel, IssueReporterData as IssueReporterModelData } from 'vs/workbench/contrib/issue/browser/issueReporterModel';
import { mainWindow } from 'vs/base/browser/window';
const MAX_URL_LENGTH = 7500;
@ -156,7 +157,7 @@ export class BaseIssueReporterService extends Disposable {
const content: string[] = [];
if (styles.inputBackground) {
content.push(`input[type="text"], textarea, select, .issues-container > .issue > .issue-state, .block-info { background-color: ${styles.inputBackground}; }`);
content.push(`input[type="text"], textarea, select, .issues-container > .issue > .issue-state, .block-info { background-color: ${styles.inputBackground} !important; }`);
}
if (styles.inputBorder) {
@ -166,7 +167,7 @@ export class BaseIssueReporterService extends Disposable {
}
if (styles.inputForeground) {
content.push(`input[type="text"], textarea, select, .issues-container > .issue > .issue-state, .block-info { color: ${styles.inputForeground}; }`);
content.push(`input[type="text"], textarea, select, .issues-container > .issue > .issue-state, .block-info { color: ${styles.inputForeground} !important; }`);
}
if (styles.inputErrorBorder) {
@ -825,7 +826,8 @@ export class BaseIssueReporterService extends Disposable {
}),
headers: new Headers({
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.data.githubAccessToken}`
'Authorization': `Bearer ${this.data.githubAccessToken}`,
'User-Agent': 'request'
})
};
@ -835,8 +837,7 @@ export class BaseIssueReporterService extends Disposable {
return false;
}
const result = await response.json();
this.window.open(result.html_url, '_blank');
mainWindow.open(result.html_url, '_blank');
this.close();
return true;
}

View file

@ -0,0 +1,180 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { safeInnerHtml } from 'vs/base/browser/dom';
import { mainWindow } from 'vs/base/browser/window';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import BaseHtml from 'vs/workbench/contrib/issue/browser/issueReporterPage';
import 'vs/css!./media/issueReporter';
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { PerformanceInfo, SystemInfo } from 'vs/platform/diagnostics/common/diagnostics';
import { ExtensionIdentifier, ExtensionIdentifierSet } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IIssueMainService, IssueReporterData, ProcessExplorerData } from 'vs/platform/issue/common/issue';
import product from 'vs/platform/product/common/product';
import { IssueWebReporter } from 'vs/workbench/contrib/issue/browser/issueReporterService';
import { AuxiliaryWindowMode, IAuxiliaryWindowService } from 'vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService';
export class IssueFormService implements IIssueMainService {
readonly _serviceBrand: undefined;
private issueReporterWindow: Window | null = null;
private extensionIdentifierSet: ExtensionIdentifierSet = new ExtensionIdentifierSet();
constructor(
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IAuxiliaryWindowService private readonly auxiliaryWindowService: IAuxiliaryWindowService,
@IMenuService private readonly menuService: IMenuService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
) {
// listen for messages from the main window
mainWindow.addEventListener('message', async (event) => {
if (event.data && event.data.sendChannel === 'vscode:triggerReporterMenu') {
// creates menu from contributed
const menu = this.menuService.createMenu(MenuId.IssueReporter, this.contextKeyService);
// render menu and dispose
const actions = menu.getActions({ renderShortTitle: true }).flatMap(entry => entry[1]);
for (const action of actions) {
try {
if (action.item && 'source' in action.item && action.item.source?.id === event.data.extensionId) {
this.extensionIdentifierSet.add(event.data.extensionId);
await action.run();
}
} catch (error) {
console.error(error);
}
}
if (!this.extensionIdentifierSet.has(event.data.extensionId)) {
// send undefined to indicate no action was taken
const replyChannel = `vscode:triggerReporterMenuResponse`;
mainWindow.postMessage({ replyChannel }, '*');
}
menu.dispose();
}
});
}
async openReporter(data: IssueReporterData): Promise<void> {
if (data.extensionId && this.extensionIdentifierSet.has(data.extensionId)) {
const replyChannel = `vscode:triggerReporterMenuResponse`;
mainWindow.postMessage({ data, replyChannel }, '*');
this.extensionIdentifierSet.delete(new ExtensionIdentifier(data.extensionId));
}
if (this.issueReporterWindow) {
this.issueReporterWindow.focus();
return;
}
const disposables = new DisposableStore();
// Auxiliary Window
const auxiliaryWindow = disposables.add(await this.auxiliaryWindowService.open({ mode: AuxiliaryWindowMode.Normal }));
this.issueReporterWindow = auxiliaryWindow.window;
if (auxiliaryWindow) {
await auxiliaryWindow.whenStylesHaveLoaded;
auxiliaryWindow.window.document.title = 'Issue Reporter';
auxiliaryWindow.window.document.body.classList.add('issue-reporter-body');
// custom issue reporter wrapper
const div = document.createElement('div');
div.classList.add('monaco-workbench');
// removes preset monaco-workbench
auxiliaryWindow.container.remove();
auxiliaryWindow.window.document.body.appendChild(div);
safeInnerHtml(div, BaseHtml());
// create issue reporter and instantiate
const issueReporter = this.instantiationService.createInstance(IssueWebReporter, false, data, { type: '', arch: '', release: '' }, product, auxiliaryWindow.window);
issueReporter.render();
} else {
console.error('Failed to open auxiliary window');
}
// handle closing issue reporter
this.issueReporterWindow?.addEventListener('beforeunload', () => {
auxiliaryWindow.window.close();
this.issueReporterWindow = null;
});
}
async openProcessExplorer(data: ProcessExplorerData): Promise<void> {
throw new Error('Method not implemented.');
}
stopTracing(): Promise<void> {
throw new Error('Method not implemented.');
}
getSystemStatus(): Promise<string> {
throw new Error('Method not implemented.');
}
$getSystemInfo(): Promise<SystemInfo> {
throw new Error('Method not implemented.');
}
$getPerformanceInfo(): Promise<PerformanceInfo> {
throw new Error('Method not implemented.');
}
$reloadWithExtensionsDisabled(): Promise<void> {
throw new Error('Method not implemented.');
}
$showConfirmCloseDialog(): Promise<void> {
throw new Error('Method not implemented.');
}
$showClipboardDialog(): Promise<boolean> {
throw new Error('Method not implemented.');
}
$getIssueReporterUri(extensionId: string): Promise<URI> {
throw new Error('Method not implemented.');
}
$getIssueReporterData(extensionId: string): Promise<string> {
throw new Error('Method not implemented.');
}
$getIssueReporterTemplate(extensionId: string): Promise<string> {
throw new Error('Method not implemented.');
}
$getReporterStatus(extensionId: string, extensionName: string): Promise<boolean[]> {
throw new Error('Method not implemented.');
}
async $sendReporterMenu(extensionId: string, extensionName: string): Promise<IssueReporterData | undefined> {
const sendChannel = `vscode:triggerReporterMenu`;
mainWindow.postMessage({ sendChannel, extensionId, extensionName }, '*');
const result = await new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
mainWindow.removeEventListener('message', listener);
reject(new Error('Timeout exceeded'));
}, 5000); // Set the timeout value in milliseconds (e.g., 5000 for 5 seconds)
const listener = (event: MessageEvent) => {
const replyChannel = `vscode:triggerReporterMenuResponse`;
if (event.data && event.data.replyChannel === replyChannel) {
clearTimeout(timeout);
mainWindow.removeEventListener('message', listener);
resolve(event.data.data);
}
};
mainWindow.addEventListener('message', listener);
});
return result as IssueReporterData | undefined;
}
async $closeReporter(): Promise<void> {
this.issueReporterWindow?.close();
}
}

View file

@ -13,6 +13,7 @@ export interface IssueReporterData {
versionInfo?: any;
systemInfo?: SystemInfo;
systemInfoWeb?: string;
processInfo?: string;
workspaceInfo?: string;
@ -138,6 +139,10 @@ ${this.getInfos()}
if (this._data.includeSystemInfo && this._data.systemInfo) {
info += this.generateSystemInfoMd();
}
if (this._data.includeSystemInfo && this._data.systemInfoWeb) {
info += 'System Info: ' + this._data.systemInfoWeb;
}
}
if (this._data.issueType === IssueType.PerformanceIssue) {

View file

@ -24,7 +24,7 @@ const reviewGuidanceLabel = localize( // intentionally not escaped because of it
);
export default (): string => `
<div id="issue-reporter">
<div class="issue-reporter" id="issue-reporter">
<div id="english" class="input-group hidden">${escape(localize('completeInEnglish', "Please complete the form in English."))}</div>
<div id="review-guidance-help-text" class="input-group">${reviewGuidanceLabel}</div>

View file

@ -3,12 +3,14 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { $, reset, windowOpenNoOpener } from 'vs/base/browser/dom';
import { Codicon } from 'vs/base/common/codicons';
import { groupBy } from 'vs/base/common/collections';
import { isMacintosh } from 'vs/base/common/platform';
import { IProductConfiguration } from 'vs/base/common/product';
import { BaseIssueReporterService } from 'vs/code/browser/issue/issue';
import { ThemeIcon } from 'vs/base/common/themables';
import { localize } from 'vs/nls';
import { IIssueMainService, IssueReporterData, IssueReporterExtensionData } from 'vs/platform/issue/common/issue';
import { BaseIssueReporterService } from 'vs/workbench/contrib/issue/browser/issue';
// GitHub has let us know that we could up our limit here to 8k. We chose 7500 to play it safe.
// ref https://github.com/microsoft/vscode/issues/159191
@ -27,6 +29,17 @@ export class IssueWebReporter extends BaseIssueReporterService {
@IIssueMainService issueMainService: IIssueMainService
) {
super(disableExtensions, data, os, product, window, true, issueMainService);
const target = this.window.document.querySelector<HTMLElement>('.block-system .block-info');
const webInfo = this.window.navigator.userAgent;
if (webInfo) {
target?.appendChild(this.window.document.createTextNode(webInfo));
this.receivedSystemInfo = true;
this.issueReporterModel.update({ systemInfoWeb: webInfo });
}
this.setEventHandlers();
this.handleExtensionData(data.enabledExtensions);
}
@ -174,7 +187,31 @@ export class IssueWebReporter extends BaseIssueReporterService {
this.issueReporterModel.update({ selectedExtension: matches[0] });
const selectedExtension = this.issueReporterModel.getData().selectedExtension;
if (selectedExtension) {
await this.sendReporterMenu(selectedExtension);
const iconElement = document.createElement('span');
iconElement.classList.add(...ThemeIcon.asClassNameArray(Codicon.loading), 'codicon-modifier-spin');
this.setLoading(iconElement);
const openReporterData = await this.sendReporterMenu(selectedExtension);
if (openReporterData) {
if (this.selectedExtension === selectedExtensionId) {
this.removeLoading(iconElement, true);
this.data = openReporterData;
} else if (this.selectedExtension !== selectedExtensionId) {
}
}
else {
if (!this.loadingExtensionData) {
iconElement.classList.remove(...ThemeIcon.asClassNameArray(Codicon.loading), 'codicon-modifier-spin');
}
this.removeLoading(iconElement);
this.clearExtensionData();
selectedExtension.data = undefined;
selectedExtension.uri = undefined;
}
if (this.selectedExtension === selectedExtensionId) {
// repopulates the fields with the new data given the selected extension.
this.updateExtensionStatus(matches[0]);
this.openReporter = false;
}
} else {
this.issueReporterModel.update({ selectedExtension: undefined });
this.clearSearchResults();

View file

@ -0,0 +1,210 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from 'vs/base/browser/dom';
import { userAgent } from 'vs/base/common/platform';
import { IExtensionDescription, ExtensionType } from 'vs/platform/extensions/common/extensions';
import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil';
import { getZoomLevel } from 'vs/base/browser/browser';
import { mainWindow } from 'vs/base/browser/window';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IIssueMainService, IssueReporterData, IssueReporterExtensionData, IssueReporterStyles } from 'vs/platform/issue/common/issue';
import { IProductService } from 'vs/platform/product/common/productService';
import { buttonBackground, buttonForeground, buttonHoverBackground, foreground, inputActiveOptionBorder, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, textLinkActiveForeground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry';
import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService';
import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { IWorkbenchAssignmentService } from 'vs/workbench/services/assignment/common/assignmentService';
import { IAuthenticationService } from 'vs/workbench/services/authentication/common/authentication';
import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IIntegrityService } from 'vs/workbench/services/integrity/common/integrity';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/common/issue';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
export class BrowserIssueService implements IWorkbenchIssueService {
declare readonly _serviceBrand: undefined;
constructor(
@IExtensionService private readonly extensionService: IExtensionService,
@IProductService private readonly productService: IProductService,
@IIssueMainService private readonly issueMainService: IIssueMainService,
@IThemeService private readonly themeService: IThemeService,
@IWorkbenchAssignmentService private readonly experimentService: IWorkbenchAssignmentService,
@IWorkspaceTrustManagementService private readonly workspaceTrustManagementService: IWorkspaceTrustManagementService,
@IIntegrityService private readonly integrityService: IIntegrityService,
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
@IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService,
@IAuthenticationService private readonly authenticationService: IAuthenticationService,
@IConfigurationService private readonly configurationService: IConfigurationService
) { }
//TODO @TylerLeonhardt @Tyriar to implement a process explorer for the web
async openProcessExplorer(): Promise<void> {
console.error('openProcessExplorer is not implemented in web');
}
async openReporter(options: Partial<IssueReporterData>): Promise<void> {
if (!this.configurationService.getValue<boolean>('issueReporter.experimental.webReporter')) {
const extensionId = options.extensionId;
// If we don't have a extensionId, treat this as a Core issue
if (!extensionId) {
if (this.productService.reportIssueUrl) {
const uri = this.getIssueUriFromStaticContent(this.productService.reportIssueUrl);
dom.windowOpenNoOpener(uri);
return;
}
throw new Error(`No issue reporting URL configured for ${this.productService.nameLong}.`);
}
const selectedExtension = this.extensionService.extensions.filter(ext => ext.identifier.value === options.extensionId)[0];
const extensionGitHubUrl = this.getExtensionGitHubUrl(selectedExtension);
if (!extensionGitHubUrl) {
throw new Error(`Unable to find issue reporting url for ${extensionId}`);
}
const uri = this.getIssueUriFromStaticContent(`${extensionGitHubUrl}/issues/new`, selectedExtension);
dom.windowOpenNoOpener(uri);
}
if (this.productService.reportIssueUrl) {
const theme = this.themeService.getColorTheme();
const experiments = await this.experimentService.getCurrentExperiments();
let githubAccessToken = '';
try {
const githubSessions = await this.authenticationService.getSessions('github');
const potentialSessions = githubSessions.filter(session => session.scopes.includes('repo'));
githubAccessToken = potentialSessions[0]?.accessToken;
} catch (e) {
// Ignore
}
// air on the side of caution and have false be the default
let isUnsupported = false;
try {
isUnsupported = !(await this.integrityService.isPure()).isPure;
} catch (e) {
// Ignore
}
const extensionData: IssueReporterExtensionData[] = [];
try {
const extensions = await this.extensionManagementService.getInstalled();
const enabledExtensions = extensions.filter(extension => this.extensionEnablementService.isEnabled(extension) || (options.extensionId && extension.identifier.id === options.extensionId));
extensionData.push(...enabledExtensions.map((extension): IssueReporterExtensionData => {
const { manifest } = extension;
const manifestKeys = manifest.contributes ? Object.keys(manifest.contributes) : [];
const isTheme = !manifest.main && !manifest.browser && manifestKeys.length === 1 && manifestKeys[0] === 'themes';
const isBuiltin = extension.type === ExtensionType.System;
return {
name: manifest.name,
publisher: manifest.publisher,
version: manifest.version,
repositoryUrl: manifest.repository && manifest.repository.url,
bugsUrl: manifest.bugs && manifest.bugs.url,
displayName: manifest.displayName,
id: extension.identifier.id,
data: options.data,
uri: options.uri,
isTheme,
isBuiltin,
extensionData: 'Extensions data loading',
};
}));
} catch (e) {
extensionData.push({
name: 'Workbench Issue Service',
publisher: 'Unknown',
version: 'Unknown',
repositoryUrl: undefined,
bugsUrl: undefined,
extensionData: `Extensions not loaded: ${e}`,
displayName: `Extensions not loaded: ${e}`,
id: 'workbench.issue',
isTheme: false,
isBuiltin: true
});
}
const issueReporterData: IssueReporterData = Object.assign({
styles: getIssueReporterStyles(theme),
zoomLevel: getZoomLevel(mainWindow),
enabledExtensions: extensionData,
experiments: experiments?.join('\n'),
restrictedMode: !this.workspaceTrustManagementService.isWorkspaceTrusted(),
isUnsupported,
githubAccessToken
}, options);
return this.issueMainService.openReporter(issueReporterData);
}
throw new Error(`No issue reporting URL configured for ${this.productService.nameLong}.`);
}
private getExtensionGitHubUrl(extension: IExtensionDescription): string {
if (extension.isBuiltin && this.productService.reportIssueUrl) {
return normalizeGitHubUrl(this.productService.reportIssueUrl);
}
let repositoryUrl = '';
const bugsUrl = extension?.bugs?.url;
const extensionUrl = extension?.repository?.url;
// If given, try to match the extension's bug url
if (bugsUrl && bugsUrl.match(/^https?:\/\/github\.com\/(.*)/)) {
repositoryUrl = normalizeGitHubUrl(bugsUrl);
} else if (extensionUrl && extensionUrl.match(/^https?:\/\/github\.com\/(.*)/)) {
repositoryUrl = normalizeGitHubUrl(extensionUrl);
}
return repositoryUrl;
}
private getIssueUriFromStaticContent(baseUri: string, extension?: IExtensionDescription): string {
const issueDescription = `ADD ISSUE DESCRIPTION HERE
Version: ${this.productService.version}
Commit: ${this.productService.commit ?? 'unknown'}
User Agent: ${userAgent ?? 'unknown'}
Embedder: ${this.productService.embedderIdentifier ?? 'unknown'}
${extension?.version ? `\nExtension version: ${extension.version}` : ''}
<!-- generated by web issue reporter -->`;
return `${baseUri}?body=${encodeURIComponent(issueDescription)}&labels=web`;
}
}
export function getIssueReporterStyles(theme: IColorTheme): IssueReporterStyles {
return {
backgroundColor: getColor(theme, SIDE_BAR_BACKGROUND),
color: getColor(theme, foreground),
textLinkColor: getColor(theme, textLinkForeground),
textLinkActiveForeground: getColor(theme, textLinkActiveForeground),
inputBackground: getColor(theme, inputBackground),
inputForeground: getColor(theme, inputForeground),
inputBorder: getColor(theme, inputBorder),
inputActiveBorder: getColor(theme, inputActiveOptionBorder),
inputErrorBorder: getColor(theme, inputValidationErrorBorder),
inputErrorBackground: getColor(theme, inputValidationErrorBackground),
inputErrorForeground: getColor(theme, inputValidationErrorForeground),
buttonBackground: getColor(theme, buttonBackground),
buttonForeground: getColor(theme, buttonForeground),
buttonHoverBackground: getColor(theme, buttonHoverBackground),
sliderActiveColor: getColor(theme, scrollbarSliderActiveBackground),
sliderBackgroundColor: getColor(theme, scrollbarSliderBackground),
sliderHoverColor: getColor(theme, scrollbarSliderHoverBackground),
};
}
function getColor(theme: IColorTheme, key: string): string | undefined {
const color = theme.getColor(key);
return color ? color.toString() : undefined;
}
registerSingleton(IWorkbenchIssueService, BrowserIssueService, InstantiationType.Delayed);

View file

@ -7,7 +7,7 @@ import { localize, localize2 } from 'vs/nls';
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { IProductService } from 'vs/platform/product/common/productService';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/common/issue';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
import { IUserDataProfileImportExportService, IUserDataProfileManagementService, IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';

View file

@ -0,0 +1,459 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.mac.web.issue-reporter-body {
position: absolute;
overflow-y: scroll;
}
.web.issue-reporter-body .monaco-workbench select{
-webkit-appearance: auto;
appearance: auto;
}
/**
* Table
*/
.issue-reporter table {
width: 100%;
max-width: 100%;
background-color: transparent;
border-collapse: collapse;
}
.issue-reporter th {
vertical-align: bottom;
border-bottom: 1px solid;
padding: 5px;
text-align: inherit;
}
.issue-reporter td {
padding: 5px;
vertical-align: top;
}
.issue-reporter tr td:first-child {
width: 30%;
}
.issue-reporter label {
user-select: none;
}
.issue-reporter .block-settingsSearchResults-details {
padding-bottom: .5rem;
}
.issue-reporter .block-settingsSearchResults-details > div {
padding: .5rem .75rem;
}
.issue-reporter .section {
margin-bottom: .5em;
}
/**
* Forms
*/
.issue-reporter input[type="text"],
.issue-reporter textarea {
display: block;
width: 100%;
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
color: #495057;
background-color: #fff;
border: 1px solid #ced4da;
}
.issue-reporter textarea {
overflow: auto;
resize: vertical;
}
/**
* Button
*/
.issue-reporter .monaco-text-button {
display: block;
width: auto;
padding: 4px 10px;
align-self: flex-end;
margin-bottom: 1em;
font-size: 13px;
}
.issue-reporter select {
height: calc(2.25rem + 2px);
display: inline-block;
padding: 3px 3px;
font-size: 14px;
line-height: 1.5;
color: #495057;
background-color: #fff;
border: none;
}
.issue-reporter * {
box-sizing: border-box;
}
.issue-reporter textarea,
.issue-reporter input,
.issue-reporter select {
font-family: inherit;
}
.issue-reporter html {
color: #CCCCCC;
height: 100%;
}
.issue-reporter .extension-caption .codicon-modifier-spin {
padding-bottom: 3px;
margin-left: 2px;
}
/* Font Families (with CJK support) */
.issue-reporter .mac.web {
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
}
.issue-reporter .mac.web:lang(zh-Hans) {
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif;
}
.issue-reporter .mac.web:lang(zh-Hant) {
font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif;
}
.issue-reporter .mac.web:lang(ja) {
font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif;
}
.issue-reporter .mac.web:lang(ko) {
font-family: -apple-system, BlinkMacSystemFont, "Nanum Gothic", "Apple SD Gothic Neo", "AppleGothic", sans-serif;
}
.issue-reporter .windows.web {
font-family: "Segoe WPC", "Segoe UI", sans-serif;
}
.issue-reporter .windows.web:lang(zh-Hans) {
font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif;
}
.issue-reporter .windows.web:lang(zh-Hant) {
font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif;
}
.issue-reporter .windows.web:lang(ja) {
font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif;
}
.issue-reporter .windows.web:lang(ko) {
font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif;
}
.issue-reporter .linux.web {
font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif;
}
.issue-reporter .linux.web:lang(zh-Hans) {
font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif;
}
.issue-reporter .linux.web:lang(zh-Hant) {
font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif;
}
.issue-reporter .linux.web:lang(ja) {
font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif;
}
.issue-reporter .linux.web:lang(ko) {
font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif;
}
.issue-reporter body {
margin: 0;
overflow-y: scroll;
height: 100%;
}
.issue-reporter .hidden {
display: none;
}
.issue-reporter .block {
font-size: 12px;
}
.issue-reporter .block .block-info {
width: 100%;
font-size: 12px;
overflow: auto;
overflow-wrap: break-word;
margin: 5px;
padding: 10px;
}
.issue-reporter {
max-width: 85vw;
margin-left: auto;
margin-right: auto;
padding-top: 2em;
padding-bottom: 2em;
display: flex;
flex-direction: column;
min-height: 100%;
overflow: visible;
}
.issue-reporter .description-section {
flex-grow: 1;
display: flex;
flex-direction: column;
flex-shrink: 0;
}
.issue-reporter textarea {
flex-grow: 1;
min-height: 150px;
}
.issue-reporter .block-info-text {
display: flex;
flex-grow: 1;
}
.issue-reporter #github-submit-btn {
flex-shrink: 0;
margin-left: auto;
margin-top: 10px;
margin-bottom: 10px;
}
.issue-reporter .two-col {
display: inline-block;
width: 49%;
}
.issue-reporter #vscode-version {
width: 90%;
}
.issue-reporter .input-group {
margin-bottom: 1em;
font-size: 16px;
}
.issue-reporter #extension-selection {
margin-top: 1em;
}
.issue-reporter select,
.issue-reporter input,
.issue-reporter textarea {
border: 1px solid transparent;
margin-top: 10px;
}
.issue-reporter .validation-error {
font-size: 12px;
padding: 10px;
border-top: 0px !important;
}
.issue-reporter .system-info {
margin-bottom: 10px;
}
.issue-reporter input[type="checkbox"] {
width: auto;
display: inline-block;
margin-top: 0;
vertical-align: middle;
cursor: pointer;
}
.issue-reporter input:disabled {
opacity: 0.6;
}
.issue-reporter .list-title {
margin-top: 1em;
margin-left: 1em;
}
.issue-reporter .instructions {
font-size: 12px;
margin-top: .5em;
}
.issue-reporter a,
.issue-reporter .workbenchCommand {
cursor: pointer;
border: 1px solid transparent;
}
.issue-reporter .workbenchCommand:disabled {
color: #868e96;
cursor: default
}
.issue-reporter .block-extensions .block-info {
margin-bottom: 1.5em;
}
/* Default styles, overwritten if a theme is provided */
.issue-reporter input,
.issue-reporter select,
.issue-reporter textarea {
background-color: #3c3c3c;
border: none;
color: #cccccc;
}
.issue-reporter .section .input-group .validation-error {
margin-left: 100px;
}
.issue-reporter .section .inline-form-control,
.issue-reporter .section .inline-label {
display: inline-block;
}
.issue-reporter .section .inline-label {
width: 95px;
}
.issue-reporter .section .inline-form-control,
.issue-reporter .section .input-group .validation-error {
width: calc(100% - 100px);
}
.issue-reporter #issue-type {
cursor: pointer;
}
.issue-reporter #similar-issues {
margin-left: 15%;
display: block;
}
.issue-reporter #problem-source-help-text {
margin-left: calc(15% + 1em);
}
@media (max-width: 950px) {
.issue-reporter .section .inline-label {
width: 15%;
font-size: 16px;
}
.issue-reporter #problem-source-help-text {
margin-left: calc(15% + 1em);
}
.issue-reporter .section .inline-form-control,
.issue-reporter .section .input-group .validation-error {
width: calc(85% - 5px);
}
.issue-reporter .section .input-group .validation-error {
margin-left: calc(15% + 4px);
}
}
@media (max-width: 620px) {
.issue-reporter .section .inline-label {
display: none !important;
}
.issue-reporter #problem-source-help-text {
margin-left: 1em;
}
.issue-reporter .section .inline-form-control,
.issue-reporter .section .input-group .validation-error {
width: 100%;
}
.issue-reporter #similar-issues,
.issue-reporter .section .input-group .validation-error {
margin-left: 0;
}
}
.issue-reporter ::-webkit-scrollbar {
width: 14px;
}
.issue-reporter ::-webkit-scrollbar-thumb {
min-height: 20px;
}
.issue-reporter ::-webkit-scrollbar-corner {
display: none;
}
.issue-reporter .issues-container {
margin-left: 1.5em;
margin-top: .5em;
max-height: 92px;
overflow-y: auto;
}
.issue-reporter .issues-container > .issue {
padding: 4px 0;
display: flex;
}
.issue-reporter .issues-container > .issue > .issue-link {
width: calc(100% - 82px);
overflow: hidden;
padding-top: 3px;
white-space: nowrap;
text-overflow: ellipsis;
}
.issue-reporter .issues-container > .issue > .issue-state .codicon {
width: 16px;
}
.issue-reporter .issues-container > .issue > .issue-state {
display: flex;
width: 77px;
padding: 3px 6px;
margin-right: 5px;
color: #CCCCCC;
background-color: #3c3c3c;
border-radius: .25rem;
}
.issue-reporter .issues-container > .issue .label {
padding-top: 2px;
margin-left: 5px;
width: 44px;
text-overflow: ellipsis;
overflow: hidden;
}
.issue-reporter .issues-container > .issue .issue-icon {
padding-top: 2px;
}
.issue-reporter a {
color: var(--vscode-textLink-foreground);
}

View file

@ -11,7 +11,7 @@ import { CommandsRegistry, ICommandMetadata } from 'vs/platform/commands/common/
import { IssueReporterData } from 'vs/platform/issue/common/issue';
import { IProductService } from 'vs/platform/product/common/productService';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/common/issue';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { Disposable } from 'vs/base/common/lifecycle';

View file

@ -5,7 +5,7 @@
import { localize, localize2 } from 'vs/nls';
import { MenuRegistry, MenuId, registerAction2, Action2 } from 'vs/platform/actions/common/actions';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/common/issue';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { BaseIssueContribution } from 'vs/workbench/contrib/issue/common/issue.contribution';
import { IProductService } from 'vs/platform/product/common/productService';
@ -23,6 +23,9 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { IDisposable } from 'vs/base/common/lifecycle';
import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/platform/quickinput/common/quickAccess';
import { IssueQuickAccess } from 'vs/workbench/contrib/issue/browser/issueQuickAccess';
import 'vs/workbench/contrib/issue/electron-sandbox/issueMainService';
import 'vs/workbench/contrib/issue/electron-sandbox/issueService';
import 'vs/workbench/contrib/issue/browser/issueTroubleshoot';
//#region Issue Contribution

View file

@ -39,8 +39,8 @@
</body>
<!-- Startup (do not modify order of script tags!) -->
<script src="../../../../bootstrap.js"></script>
<script src="../../../../vs/loader.js"></script>
<script src="../../../../bootstrap-window.js"></script>
<script src="../../../../../bootstrap.js"></script>
<script src="../../../../../vs/loader.js"></script>
<script src="../../../../../bootstrap-window.js"></script>
<script src="issueReporter.js"></script>
</html>

View file

@ -10,7 +10,7 @@
const bootstrapWindow = bootstrapWindowLib();
// Load issue reporter into window
bootstrapWindow.load(['vs/code/electron-sandbox/issue/issueReporterMain'], function (issueReporter, configuration) {
bootstrapWindow.load(['vs/workbench/contrib/issue/electron-sandbox/issueReporterMain'], function (issueReporter, configuration) {
return issueReporter.startup(configuration);
},
{
@ -24,7 +24,7 @@
);
/**
* @typedef {import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration} ISandboxConfiguration
* @typedef {import('../../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration} ISandboxConfiguration
*
* @returns {{
* load: (

View file

@ -6,7 +6,7 @@
import { safeInnerHtml } from 'vs/base/browser/dom';
import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded
import { isLinux, isWindows } from 'vs/base/common/platform';
import BaseHtml from 'vs/code/browser/issue/issueReporterPage';
import BaseHtml from 'vs/workbench/contrib/issue/browser/issueReporterPage';
import 'vs/css!./media/issueReporter';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions';
@ -18,7 +18,7 @@ import { registerMainProcessRemoteService } from 'vs/platform/ipc/electron-sandb
import { IIssueMainService, IssueReporterWindowConfiguration } from 'vs/platform/issue/common/issue';
import { INativeHostService } from 'vs/platform/native/common/native';
import { NativeHostService } from 'vs/platform/native/common/nativeHostService';
import { IssueReporter2 } from 'vs/code/electron-sandbox/issue/issueReporterService2';
import { IssueReporter2 } from 'vs/workbench/contrib/issue/electron-sandbox/issueReporterService2';
import { mainWindow } from 'vs/base/browser/window';
export function startup(configuration: IssueReporterWindowConfiguration) {

View file

@ -16,7 +16,7 @@ import { isLinuxSnap, isMacintosh } from 'vs/base/common/platform';
import { escape } from 'vs/base/common/strings';
import { ThemeIcon } from 'vs/base/common/themables';
import { URI } from 'vs/base/common/uri';
import { IssueReporterModel, IssueReporterData as IssueReporterModelData } from 'vs/code/browser/issue/issueReporterModel';
import { IssueReporterModel, IssueReporterData as IssueReporterModelData } from 'vs/workbench/contrib/issue/browser/issueReporterModel';
import { localize } from 'vs/nls';
import { isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
import { IIssueMainService, IssueReporterData, IssueReporterExtensionData, IssueReporterStyles, IssueReporterWindowConfiguration, IssueType } from 'vs/platform/issue/common/issue';

View file

@ -10,13 +10,13 @@ import { CancellationError } from 'vs/base/common/errors';
import { isMacintosh } from 'vs/base/common/platform';
import { ThemeIcon } from 'vs/base/common/themables';
import { URI } from 'vs/base/common/uri';
import { IssueReporterData as IssueReporterModelData } from 'vs/code/browser/issue/issueReporterModel';
import { BaseIssueReporterService, hide, show } from 'vs/code/browser/issue/issue';
import { localize } from 'vs/nls';
import { isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
import { IIssueMainService, IssueReporterData, IssueReporterExtensionData, IssueReporterWindowConfiguration, IssueType } from 'vs/platform/issue/common/issue';
import { INativeHostService } from 'vs/platform/native/common/native';
import { applyZoom, zoomIn, zoomOut } from 'vs/platform/window/electron-sandbox/window';
import { BaseIssueReporterService, hide, show } from 'vs/workbench/contrib/issue/browser/issue';
import { IssueReporterData as IssueReporterModelData } from 'vs/workbench/contrib/issue/browser/issueReporterModel';
// GitHub has let us know that we could up our limit here to 8k. We chose 7500 to play it safe.
// ref https://github.com/microsoft/vscode/issues/159191

View file

@ -20,7 +20,7 @@ import { IAuthenticationService } from 'vs/workbench/services/authentication/com
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IIntegrityService } from 'vs/workbench/services/integrity/common/integrity';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/common/issue';
import { mainWindow } from 'vs/base/browser/window';
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';

View file

@ -5,7 +5,7 @@
import * as assert from 'assert';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { IssueReporterModel } from 'vs/code/browser/issue/issueReporterModel';
import { IssueReporterModel } from 'vs/workbench/contrib/issue/browser/issueReporterModel';
import { IssueType } from 'vs/platform/issue/common/issue';
import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil';

View file

@ -50,7 +50,7 @@ import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { ctxIsMergeResultEditor, ctxMergeBaseUri } from 'vs/workbench/contrib/mergeEditor/common/mergeEditor';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/common/issue';
import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
import { ILocalizedString } from 'vs/platform/action/common/action';
import { isWeb } from 'vs/base/common/platform';

View file

@ -20,7 +20,6 @@ import { Extensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ILogService } from 'vs/platform/log/common/log';
import { IProductService } from 'vs/platform/product/common/productService';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { Categories } from 'vs/platform/action/common/actionCommonCategories';
@ -271,7 +270,7 @@ registerAction2(class extends Action2 {
const bisectService = accessor.get(IExtensionBisectService);
const productService = accessor.get(IProductService);
const extensionEnablementService = accessor.get(IGlobalExtensionEnablementService);
const issueService = accessor.get(IWorkbenchIssueService);
const commandService = accessor.get(ICommandService);
if (!bisectService.isActive) {
return;
@ -315,7 +314,7 @@ registerAction2(class extends Action2 {
await extensionEnablementService.disableExtension({ id: done.id }, undefined);
}
if (res.confirmed) {
await issueService.openReporter({ extensionId: done.id });
await commandService.executeCommand('workbench.action.openIssueReporter', done.id);
}
}
await bisectService.reset();

View file

@ -1,82 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from 'vs/base/browser/dom';
import { userAgent } from 'vs/base/common/platform';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { IssueReporterData } from 'vs/platform/issue/common/issue';
import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil';
import { IProductService } from 'vs/platform/product/common/productService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
export class WebIssueService implements IWorkbenchIssueService {
declare readonly _serviceBrand: undefined;
constructor(
@IExtensionService private readonly extensionService: IExtensionService,
@IProductService private readonly productService: IProductService,
) { }
//TODO @TylerLeonhardt @Tyriar to implement a process explorer for the web
async openProcessExplorer(): Promise<void> {
console.error('openProcessExplorer is not implemented in web');
}
async openReporter(options: Partial<IssueReporterData>): Promise<void> {
const extensionId = options.extensionId;
// If we don't have a extensionId, treat this as a Core issue
if (!extensionId) {
if (this.productService.reportIssueUrl) {
const uri = this.getIssueUriFromStaticContent(this.productService.reportIssueUrl);
dom.windowOpenNoOpener(uri);
return;
}
throw new Error(`No issue reporting URL configured for ${this.productService.nameLong}.`);
}
const selectedExtension = this.extensionService.extensions.filter(ext => ext.identifier.value === options.extensionId)[0];
const extensionGitHubUrl = this.getExtensionGitHubUrl(selectedExtension);
if (!extensionGitHubUrl) {
throw new Error(`Unable to find issue reporting url for ${extensionId}`);
}
const uri = this.getIssueUriFromStaticContent(`${extensionGitHubUrl}/issues/new`, selectedExtension);
dom.windowOpenNoOpener(uri);
}
private getExtensionGitHubUrl(extension: IExtensionDescription): string {
if (extension.isBuiltin && this.productService.reportIssueUrl) {
return normalizeGitHubUrl(this.productService.reportIssueUrl);
}
let repositoryUrl = '';
const bugsUrl = extension?.bugs?.url;
const extensionUrl = extension?.repository?.url;
// If given, try to match the extension's bug url
if (bugsUrl && bugsUrl.match(/^https?:\/\/github\.com\/(.*)/)) {
repositoryUrl = normalizeGitHubUrl(bugsUrl);
} else if (extensionUrl && extensionUrl.match(/^https?:\/\/github\.com\/(.*)/)) {
repositoryUrl = normalizeGitHubUrl(extensionUrl);
}
return repositoryUrl;
}
private getIssueUriFromStaticContent(baseUri: string, extension?: IExtensionDescription): string {
const issueDescription = `ADD ISSUE DESCRIPTION HERE
Version: ${this.productService.version}
Commit: ${this.productService.commit ?? 'unknown'}
User Agent: ${userAgent ?? 'unknown'}
Embedder: ${this.productService.embedderIdentifier ?? 'unknown'}
${extension?.version ? `\nExtension version: ${extension.version}` : ''}
<!-- generated by web issue reporter -->`;
return `${baseUri}?body=${encodeURIComponent(issueDescription)}&labels=web`;
}
}

View file

@ -117,7 +117,6 @@ import 'vs/editor/common/services/treeViewsDndService';
import 'vs/workbench/services/textMate/browser/textMateTokenizationFeature.contribution';
import 'vs/workbench/services/userActivity/common/userActivityService';
import 'vs/workbench/services/userActivity/browser/userActivityBrowser';
import 'vs/workbench/services/issue/browser/issueTroubleshoot';
import 'vs/workbench/services/editor/browser/editorPaneService';
import 'vs/workbench/services/editor/common/customEditorLabelService';

View file

@ -38,8 +38,6 @@ import 'vs/workbench/services/textfile/electron-sandbox/nativeTextFileService';
import 'vs/workbench/services/dialogs/electron-sandbox/fileDialogService';
import 'vs/workbench/services/workspaces/electron-sandbox/workspacesService';
import 'vs/workbench/services/menubar/electron-sandbox/menubarService';
import 'vs/workbench/services/issue/electron-sandbox/issueMainService';
import 'vs/workbench/services/issue/electron-sandbox/issueService';
import 'vs/workbench/services/update/electron-sandbox/updateService';
import 'vs/workbench/services/url/electron-sandbox/urlService';
import 'vs/workbench/services/lifecycle/electron-sandbox/lifecycleService';