Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

web reporter refactor and issueFormService #212951

Merged
merged 29 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
adb6479
web version working
justschen May 16, 2024
06c6cfb
change to mainWindow
justschen May 16, 2024
202a62d
PROPER MOVEMENT
justschen May 17, 2024
ca1536c
working for web as well
justschen May 17, 2024
17dfc9b
move issueFormService to workbench/contrib/issue
justschen May 17, 2024
fcb6ec7
cleaning up{
justschen May 20, 2024
c205607
more cleanup, added setting
justschen May 20, 2024
eb3f62d
styling
justschen May 21, 2024
42171b1
use mainwindow to open and closee
justschen May 21, 2024
ed04565
css fixes
justschen May 21, 2024
253381d
fix css again
justschen May 22, 2024
4a7a4d1
fix CSS and wonky applyCSS rules
justschen May 22, 2024
240eede
change gulpfile
justschen May 22, 2024
28d56df
add and update system info
justschen May 22, 2024
132b517
address some of the comments
justschen May 22, 2024
cd02d05
move files! small changes
justschen May 23, 2024
a73028d
move JS and non window specific back to electron sandbox
justschen May 23, 2024
47da475
fix on issueReporter.js
justschen May 23, 2024
6cbcc8b
fix build file
justschen May 23, 2024
232a778
fix gulp file too....
justschen May 23, 2024
c47a4a9
move everything into contrib
justschen May 23, 2024
7befb8c
fix workbench import
justschen May 23, 2024
0dc832b
move everything else into contrib, fix import
justschen May 23, 2024
a19cc3b
change name to web
justschen May 23, 2024
17234a1
applying more feedback fixes :D
justschen May 23, 2024
dd5d59b
fix command and remove unused import:
justschen May 24, 2024
e04236d
add back issueTroubleshoot
justschen May 24, 2024
434be3e
fix gulpile outputs
justschen May 24, 2024
61d4b25
fix out exclusion:
justschen May 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/gulpfile.vscode.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ 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' },
{ src: [...windowBootstrapFiles, 'out-build/vs/workbench/electron-sandbox/issues/issueReporter.js'], out: 'vs/workbench/electron-sandbox/issues/issueReporter.js' },
{ src: [...windowBootstrapFiles, 'out-build/vs/code/electron-sandbox/processExplorer/processExplorer.js'], out: 'vs/code/electron-sandbox/processExplorer/processExplorer.js' }
]
}
Expand Down
4 changes: 2 additions & 2 deletions src/buildfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -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/electron-sandbox/issues/issueReporterMain'),
];

exports.workbenchWeb = [
Expand All @@ -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')
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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/browser/issues/issueReporterModel';
import { IssueType } from 'vs/platform/issue/common/issue';
import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil';

Expand Down
2 changes: 1 addition & 1 deletion src/vs/platform/issue/electron-main/issueMainService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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/electron-sandbox/issues/issueReporter${this.environmentMainService.isBuilt ? '' : '-dev'}.html`).toString(true)
);

this.issueReporterWindow.on('close', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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/browser/issues/issueReporterModel';
import { mainWindow } from 'vs/base/browser/window';

const MAX_URL_LENGTH = 7500;

Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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'
})
};

Expand All @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface IssueReporterData {

versionInfo?: any;
systemInfo?: SystemInfo;
systemInfoWeb?: string;
processInfo?: string;
workspaceInfo?: string;

Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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/browser/issues/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
Expand All @@ -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);
}
Expand Down Expand Up @@ -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();
Expand Down
12 changes: 12 additions & 0 deletions src/vs/workbench/contrib/issue/browser/issue.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { WebIssueService } from 'vs/workbench/services/issue/browser/issueServic
import { IWorkbenchIssueService } from 'vs/workbench/services/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';


class WebIssueContribution extends BaseIssueContribution {
Expand All @@ -29,3 +30,14 @@ registerSingleton(IWorkbenchIssueService, WebIssueService, InstantiationType.Del
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.',
},
}
});
180 changes: 180 additions & 0 deletions src/vs/workbench/contrib/issue/browser/issueFormService.ts
Original file line number Diff line number Diff line change
@@ -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/browser/issues/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/browser/issues/issueReporterService';
import { AuxiliaryWindowMode, IAuxiliaryWindowService } from 'vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService';

export class IssueMainService 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.');
}

justschen marked this conversation as resolved.
Show resolved Hide resolved
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();
}
}
Loading
Loading