From 8f0188c73ff77ecc251a549e9af9b64837205fdd Mon Sep 17 00:00:00 2001 From: Justin Chen <54879025+justschen@users.noreply.github.com> Date: Wed, 30 Oct 2024 08:17:48 +0000 Subject: [PATCH] removing old issue reporter flow (#232517) * removing lot's of old issue reporter stuffs * cleanup --- build/buildfile.js | 3 - build/gulpfile.vscode.js | 7 - src/vs/code/electron-main/app.ts | 12 +- .../processExplorer/processExplorer.ts | 2 +- .../processExplorer/processExplorerMain.ts | 2 +- .../issue/common/issueReporterUtil.ts | 26 - .../issue/electron-main/issueMainService.ts | 305 ---- .../issue.ts => process/common/process.ts} | 81 -- .../electron-main/processMainService.ts | 2 +- .../issue/browser/baseIssueReporterService.ts | 3 +- .../issue/browser/issueReporterModel.ts | 3 +- .../contrib/issue/browser/issueService.ts | 2 +- .../workbench/contrib/issue/common/issue.ts | 11 - .../electron-sandbox/issue.contribution.ts | 15 +- .../electron-sandbox/issueReporter-dev.html | 46 - .../issue/electron-sandbox/issueReporter.html | 45 - .../issue/electron-sandbox/issueReporter.ts | 26 - .../electron-sandbox/issueReporterMain.ts | 57 - .../electron-sandbox/issueReporterService.ts | 1287 +---------------- .../electron-sandbox/issueReporterService2.ts | 297 ---- .../issue/electron-sandbox/issueService.ts | 125 +- .../electron-sandbox/media/issueReporter.css | 260 ++-- .../media/newIssueReporter.css | 470 ------ .../nativeIssueFormService.ts | 6 +- .../electron-sandbox/process.contribution.ts | 5 +- ...ueMainService.ts => processMainService.ts} | 3 +- .../issue/electron-sandbox/processService.ts | 2 +- 27 files changed, 229 insertions(+), 2874 deletions(-) delete mode 100644 src/vs/platform/issue/common/issueReporterUtil.ts delete mode 100644 src/vs/platform/issue/electron-main/issueMainService.ts rename src/vs/platform/{issue/common/issue.ts => process/common/process.ts} (52%) rename src/vs/platform/{issue => process}/electron-main/processMainService.ts (99%) delete mode 100644 src/vs/workbench/contrib/issue/electron-sandbox/issueReporter-dev.html delete mode 100644 src/vs/workbench/contrib/issue/electron-sandbox/issueReporter.html delete mode 100644 src/vs/workbench/contrib/issue/electron-sandbox/issueReporter.ts delete mode 100644 src/vs/workbench/contrib/issue/electron-sandbox/issueReporterMain.ts delete mode 100644 src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService2.ts delete mode 100644 src/vs/workbench/contrib/issue/electron-sandbox/media/newIssueReporter.css rename src/vs/workbench/contrib/issue/electron-sandbox/{issueMainService.ts => processMainService.ts} (76%) diff --git a/build/buildfile.js b/build/buildfile.js index 607e79e13d7..683e20fc46b 100644 --- a/build/buildfile.js +++ b/build/buildfile.js @@ -36,7 +36,6 @@ exports.workbenchDesktop = [ createModuleDescription('vs/platform/files/node/watcher/watcherMain'), createModuleDescription('vs/platform/terminal/node/ptyHostMain'), createModuleDescription('vs/workbench/api/node/extensionHostProcess'), - createModuleDescription('vs/workbench/contrib/issue/electron-sandbox/issueReporterMain'), createModuleDescription('vs/workbench/workbench.desktop.main') ]; @@ -55,8 +54,6 @@ exports.code = [ createModuleDescription('vs/code/electron-utility/sharedProcess/sharedProcessMain'), createModuleDescription('vs/code/electron-sandbox/processExplorer/processExplorerMain'), createModuleDescription('vs/code/electron-sandbox/workbench/workbench'), - // TODO: @justchen https://github.com/microsoft/vscode/issues/213332 make sure to remove when we use window.open on desktop. - createModuleDescription('vs/workbench/contrib/issue/electron-sandbox/issueReporter'), createModuleDescription('vs/code/electron-sandbox/processExplorer/processExplorer') ]; diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index f75608ba412..5dc9437bc2c 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -101,9 +101,6 @@ const vscodeResourceIncludes = [ // Tree Sitter highlights 'out-build/vs/editor/common/languages/highlights/*.scm', - - // Issue Reporter - 'out-build/vs/workbench/contrib/issue/electron-sandbox/issueReporter.html' ]; const vscodeResources = [ @@ -144,8 +141,6 @@ const bundleVSCodeTask = task.define('bundle-vscode', task.series( fileContentMapper: filePath => { if ( filePath.endsWith('vs/code/electron-sandbox/workbench/workbench.js') || - // TODO: @justchen https://github.com/microsoft/vscode/issues/213332 make sure to remove when we use window.open on desktop - filePath.endsWith('vs/workbench/contrib/issue/electron-sandbox/issueReporter.js') || filePath.endsWith('vs/code/electron-sandbox/processExplorer/processExplorer.js')) { return async (content) => { const bootstrapWindowContent = await fs.promises.readFile(path.join(root, 'out-build', 'bootstrap-window.js'), 'utf-8'); @@ -156,8 +151,6 @@ const bundleVSCodeTask = task.define('bundle-vscode', task.series( }, skipTSBoilerplateRemoval: entryPoint => entryPoint === 'vs/code/electron-sandbox/workbench/workbench' || - // TODO: @justchen https://github.com/microsoft/vscode/issues/213332 make sure to remove when we use window.open on desktop - entryPoint === 'vs/workbench/contrib/issue/electron-sandbox/issueReporter' || entryPoint === 'vs/code/electron-sandbox/processExplorer/processExplorer', } } diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index dd1e90bc65b..f334f01d5ba 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -51,9 +51,8 @@ import { DiskFileSystemProvider } from '../../platform/files/node/diskFileSystem import { SyncDescriptor } from '../../platform/instantiation/common/descriptors.js'; import { IInstantiationService, ServicesAccessor } from '../../platform/instantiation/common/instantiation.js'; import { ServiceCollection } from '../../platform/instantiation/common/serviceCollection.js'; -import { IProcessMainService, IIssueMainService } from '../../platform/issue/common/issue.js'; -import { IssueMainService } from '../../platform/issue/electron-main/issueMainService.js'; -import { ProcessMainService } from '../../platform/issue/electron-main/processMainService.js'; +import { IProcessMainService } from '../../platform/process/common/process.js'; +import { ProcessMainService } from '../../platform/process/electron-main/processMainService.js'; import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from '../../platform/keyboardLayout/electron-main/keyboardLayoutMainService.js'; import { ILaunchMainService, LaunchMainService } from '../../platform/launch/electron-main/launchMainService.js'; import { ILifecycleMainService, LifecycleMainPhase, ShutdownReason } from '../../platform/lifecycle/electron-main/lifecycleMainService.js'; @@ -1023,9 +1022,6 @@ export class CodeApplication extends Disposable { services.set(IDiagnosticsMainService, new SyncDescriptor(DiagnosticsMainService, undefined, false /* proxied to other processes */)); services.set(IDiagnosticsService, ProxyChannel.toService(getDelayedChannel(sharedProcessReady.then(client => client.getChannel('diagnostics'))))); - // Issues - services.set(IIssueMainService, new SyncDescriptor(IssueMainService, [this.userEnv])); - // Process services.set(IProcessMainService, new SyncDescriptor(ProcessMainService, [this.userEnv])); @@ -1159,10 +1155,6 @@ export class CodeApplication extends Disposable { const updateChannel = new UpdateChannel(accessor.get(IUpdateService)); mainProcessElectronServer.registerChannel('update', updateChannel); - // Issues - const issueChannel = ProxyChannel.fromService(accessor.get(IIssueMainService), disposables); - mainProcessElectronServer.registerChannel('issue', issueChannel); - // Process const processChannel = ProxyChannel.fromService(accessor.get(IProcessMainService), disposables); mainProcessElectronServer.registerChannel('process', processChannel); diff --git a/src/vs/code/electron-sandbox/processExplorer/processExplorer.ts b/src/vs/code/electron-sandbox/processExplorer/processExplorer.ts index 6df8c102be9..35db4812515 100644 --- a/src/vs/code/electron-sandbox/processExplorer/processExplorer.ts +++ b/src/vs/code/electron-sandbox/processExplorer/processExplorer.ts @@ -9,7 +9,7 @@ type IBootstrapWindow = import('vs/platform/window/electron-sandbox/window.js').IBootstrapWindow; type IProcessExplorerMain = import('vs/code/electron-sandbox/processExplorer/processExplorerMain.js').IProcessExplorerMain; - type ProcessExplorerWindowConfiguration = import('vs/platform/issue/common/issue.js').ProcessExplorerWindowConfiguration; + type ProcessExplorerWindowConfiguration = import('vs/platform/process/common/process.js').ProcessExplorerWindowConfiguration; const bootstrapWindow: IBootstrapWindow = (window as any).MonacoBootstrapWindow; // defined by bootstrap-window.ts diff --git a/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts b/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts index d9f79c61fbb..13901ed9264 100644 --- a/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts +++ b/src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts @@ -18,7 +18,7 @@ import { ipcRenderer } from '../../../base/parts/sandbox/electron-sandbox/global import { IRemoteDiagnosticError, isRemoteDiagnosticError } from '../../../platform/diagnostics/common/diagnostics.js'; import { ByteSize } from '../../../platform/files/common/files.js'; import { ElectronIPCMainProcessService } from '../../../platform/ipc/electron-sandbox/mainProcessService.js'; -import { ProcessExplorerData, ProcessExplorerStyles, ProcessExplorerWindowConfiguration } from '../../../platform/issue/common/issue.js'; +import { ProcessExplorerData, ProcessExplorerStyles, ProcessExplorerWindowConfiguration } from '../../../platform/process/common/process.js'; import { INativeHostService } from '../../../platform/native/common/native.js'; import { NativeHostService } from '../../../platform/native/common/nativeHostService.js'; import { getIconsStyleSheet } from '../../../platform/theme/browser/iconsStyleSheet.js'; diff --git a/src/vs/platform/issue/common/issueReporterUtil.ts b/src/vs/platform/issue/common/issueReporterUtil.ts deleted file mode 100644 index 3a2266e308e..00000000000 --- a/src/vs/platform/issue/common/issueReporterUtil.ts +++ /dev/null @@ -1,26 +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 { rtrim } from '../../../base/common/strings.js'; - -export function normalizeGitHubUrl(url: string): string { - // If the url has a .git suffix, remove it - if (url.endsWith('.git')) { - url = url.substr(0, url.length - 4); - } - - // Remove trailing slash - url = rtrim(url, '/'); - - if (url.endsWith('/new')) { - url = rtrim(url, '/new'); - } - - if (url.endsWith('/issues')) { - url = rtrim(url, '/issues'); - } - - return url; -} diff --git a/src/vs/platform/issue/electron-main/issueMainService.ts b/src/vs/platform/issue/electron-main/issueMainService.ts deleted file mode 100644 index 5be83d34d22..00000000000 --- a/src/vs/platform/issue/electron-main/issueMainService.ts +++ /dev/null @@ -1,305 +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 { BrowserWindow, BrowserWindowConstructorOptions, Display, screen } from 'electron'; -import { arch, release, type } from 'os'; -import { raceTimeout } from '../../../base/common/async.js'; -import { CancellationTokenSource } from '../../../base/common/cancellation.js'; -import { DisposableStore } from '../../../base/common/lifecycle.js'; -import { FileAccess } from '../../../base/common/network.js'; -import { IProcessEnvironment, isMacintosh } from '../../../base/common/platform.js'; -import { validatedIpcMain } from '../../../base/parts/ipc/electron-main/ipcMain.js'; -import { getNLSLanguage, getNLSMessages, localize } from '../../../nls.js'; -import { IDialogMainService } from '../../dialogs/electron-main/dialogMainService.js'; -import { IEnvironmentMainService } from '../../environment/electron-main/environmentMainService.js'; -import { IIssueMainService, OldIssueReporterData, OldIssueReporterWindowConfiguration } from '../common/issue.js'; -import { ILogService } from '../../log/common/log.js'; -import { INativeHostMainService } from '../../native/electron-main/nativeHostMainService.js'; -import product from '../../product/common/product.js'; -import { IIPCObjectUrl, IProtocolMainService } from '../../protocol/electron-main/protocol.js'; -import { zoomLevelToZoomFactor } from '../../window/common/window.js'; -import { ICodeWindow, IWindowState } from '../../window/electron-main/window.js'; -import { IWindowsMainService } from '../../windows/electron-main/windows.js'; -import { ICSSDevelopmentService } from '../../cssDev/node/cssDevService.js'; - -interface IBrowserWindowOptions { - backgroundColor: string | undefined; - title: string; - zoomLevel: number; - alwaysOnTop: boolean; -} - -type IStrictWindowState = Required>; - -export class IssueMainService implements IIssueMainService { - - declare readonly _serviceBrand: undefined; - - private static readonly DEFAULT_BACKGROUND_COLOR = '#1E1E1E'; - - private issueReporterWindow: BrowserWindow | null = null; - private issueReporterParentWindow: BrowserWindow | null = null; - - constructor( - private userEnv: IProcessEnvironment, - @IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService, - @ILogService private readonly logService: ILogService, - @IDialogMainService private readonly dialogMainService: IDialogMainService, - @INativeHostMainService private readonly nativeHostMainService: INativeHostMainService, - @IProtocolMainService private readonly protocolMainService: IProtocolMainService, - @IWindowsMainService private readonly windowsMainService: IWindowsMainService, - @ICSSDevelopmentService private readonly cssDevelopmentService: ICSSDevelopmentService, - ) { } - - //#region Used by renderer - - async openReporter(data: OldIssueReporterData): Promise { - if (!this.issueReporterWindow) { - this.issueReporterParentWindow = BrowserWindow.getFocusedWindow(); - if (this.issueReporterParentWindow) { - const issueReporterDisposables = new DisposableStore(); - - const issueReporterWindowConfigUrl = issueReporterDisposables.add(this.protocolMainService.createIPCObjectUrl()); - const position = this.getWindowPosition(this.issueReporterParentWindow, 700, 800); - - this.issueReporterWindow = this.createBrowserWindow(position, issueReporterWindowConfigUrl, { - backgroundColor: data.styles.backgroundColor, - title: localize('issueReporter', "Issue Reporter"), - zoomLevel: data.zoomLevel, - alwaysOnTop: false - }, 'issue-reporter'); - - // Store into config object URL - issueReporterWindowConfigUrl.update({ - appRoot: this.environmentMainService.appRoot, - windowId: this.issueReporterWindow.id, - userEnv: this.userEnv, - data, - disableExtensions: !!this.environmentMainService.disableExtensions, - os: { - type: type(), - arch: arch(), - release: release(), - }, - product, - nls: { - messages: getNLSMessages(), - language: getNLSLanguage() - }, - cssModules: this.cssDevelopmentService.isEnabled ? await this.cssDevelopmentService.getCssModules() : undefined - }); - - this.issueReporterWindow.loadURL( - FileAccess.asBrowserUri(`vs/workbench/contrib/issue/electron-sandbox/issueReporter${this.environmentMainService.isBuilt ? '' : '-dev'}.html`).toString(true) - ); - - this.issueReporterWindow.on('close', () => { - this.issueReporterWindow = null; - issueReporterDisposables.dispose(); - }); - - this.issueReporterParentWindow.on('closed', () => { - if (this.issueReporterWindow) { - this.issueReporterWindow.close(); - this.issueReporterWindow = null; - issueReporterDisposables.dispose(); - } - }); - } - } - - else if (this.issueReporterWindow) { - this.focusWindow(this.issueReporterWindow); - } - } - - //#endregion - - //#region used by issue reporter window - async $reloadWithExtensionsDisabled(): Promise { - if (this.issueReporterParentWindow) { - try { - await this.nativeHostMainService.reload(this.issueReporterParentWindow.id, { disableExtensions: true }); - } catch (error) { - this.logService.error(error); - } - } - } - - async $showConfirmCloseDialog(): Promise { - if (this.issueReporterWindow) { - const { response } = await this.dialogMainService.showMessageBox({ - type: 'warning', - message: localize('confirmCloseIssueReporter', "Your input will not be saved. Are you sure you want to close this window?"), - buttons: [ - localize({ key: 'yes', comment: ['&& denotes a mnemonic'] }, "&&Yes"), - localize('cancel', "Cancel") - ] - }, this.issueReporterWindow); - - if (response === 0) { - if (this.issueReporterWindow) { - this.issueReporterWindow.destroy(); - this.issueReporterWindow = null; - } - } - } - } - - async $showClipboardDialog(): Promise { - if (this.issueReporterWindow) { - const { response } = await this.dialogMainService.showMessageBox({ - type: 'warning', - message: localize('issueReporterWriteToClipboard', "There is too much data to send to GitHub directly. The data will be copied to the clipboard, please paste it into the GitHub issue page that is opened."), - buttons: [ - localize({ key: 'ok', comment: ['&& denotes a mnemonic'] }, "&&OK"), - localize('cancel', "Cancel") - ] - }, this.issueReporterWindow); - - return response === 0; - } - - return false; - } - - issueReporterWindowCheck(): ICodeWindow { - if (!this.issueReporterParentWindow) { - throw new Error('Issue reporter window not available'); - } - const window = this.windowsMainService.getWindowById(this.issueReporterParentWindow.id); - if (!window) { - throw new Error('Window not found'); - } - return window; - } - - async $sendReporterMenu(extensionId: string, extensionName: string): Promise { - const window = this.issueReporterWindowCheck(); - const replyChannel = `vscode:triggerReporterMenu`; - const cts = new CancellationTokenSource(); - window.sendWhenReady(replyChannel, cts.token, { replyChannel, extensionId, extensionName }); - const result = await raceTimeout(new Promise(resolve => validatedIpcMain.once(`vscode:triggerReporterMenuResponse:${extensionId}`, (_: unknown, data: OldIssueReporterData | undefined) => resolve(data))), 5000, () => { - this.logService.error(`Error: Extension ${extensionId} timed out waiting for menu response`); - cts.cancel(); - }); - return result as OldIssueReporterData | undefined; - } - - async $closeReporter(): Promise { - this.issueReporterWindow?.close(); - } - - //#endregion - - private focusWindow(window: BrowserWindow): void { - if (window.isMinimized()) { - window.restore(); - } - - window.focus(); - } - - private createBrowserWindow(position: IWindowState, ipcObjectUrl: IIPCObjectUrl, options: IBrowserWindowOptions, windowKind: string): BrowserWindow { - const windowOptions: BrowserWindowConstructorOptions & { experimentalDarkMode: boolean } = { - fullscreen: false, - skipTaskbar: false, - resizable: true, - width: position.width, - height: position.height, - minWidth: 300, - minHeight: 200, - x: position.x, - y: position.y, - title: options.title, - backgroundColor: options.backgroundColor || IssueMainService.DEFAULT_BACKGROUND_COLOR, - webPreferences: { - preload: FileAccess.asFileUri('vs/base/parts/sandbox/electron-sandbox/preload.js').fsPath, - additionalArguments: [`--vscode-window-config=${ipcObjectUrl.resource.toString()}`], - v8CacheOptions: this.environmentMainService.useCodeCache ? 'bypassHeatCheck' : 'none', - enableWebSQL: false, - spellcheck: false, - zoomFactor: zoomLevelToZoomFactor(options.zoomLevel), - sandbox: true - }, - alwaysOnTop: options.alwaysOnTop, - experimentalDarkMode: true - }; - const window = new BrowserWindow(windowOptions); - - window.setMenuBarVisibility(false); - - return window; - } - - private getWindowPosition(parentWindow: BrowserWindow, defaultWidth: number, defaultHeight: number): IStrictWindowState { - - // We want the new window to open on the same display that the parent is in - let displayToUse: Display | undefined; - const displays = screen.getAllDisplays(); - - // Single Display - if (displays.length === 1) { - displayToUse = displays[0]; - } - - // Multi Display - else { - - // on mac there is 1 menu per window so we need to use the monitor where the cursor currently is - if (isMacintosh) { - const cursorPoint = screen.getCursorScreenPoint(); - displayToUse = screen.getDisplayNearestPoint(cursorPoint); - } - - // if we have a last active window, use that display for the new window - if (!displayToUse && parentWindow) { - displayToUse = screen.getDisplayMatching(parentWindow.getBounds()); - } - - // fallback to primary display or first display - if (!displayToUse) { - displayToUse = screen.getPrimaryDisplay() || displays[0]; - } - } - - const displayBounds = displayToUse.bounds; - - const state: IStrictWindowState = { - width: defaultWidth, - height: defaultHeight, - x: displayBounds.x + (displayBounds.width / 2) - (defaultWidth / 2), - y: displayBounds.y + (displayBounds.height / 2) - (defaultHeight / 2) - }; - - if (displayBounds.width > 0 && displayBounds.height > 0 /* Linux X11 sessions sometimes report wrong display bounds */) { - if (state.x < displayBounds.x) { - state.x = displayBounds.x; // prevent window from falling out of the screen to the left - } - - if (state.y < displayBounds.y) { - state.y = displayBounds.y; // prevent window from falling out of the screen to the top - } - - if (state.x > (displayBounds.x + displayBounds.width)) { - state.x = displayBounds.x; // prevent window from falling out of the screen to the right - } - - if (state.y > (displayBounds.y + displayBounds.height)) { - state.y = displayBounds.y; // prevent window from falling out of the screen to the bottom - } - - if (state.width > displayBounds.width) { - state.width = displayBounds.width; // prevent window from exceeding display bounds width - } - - if (state.height > displayBounds.height) { - state.height = displayBounds.height; // prevent window from exceeding display bounds height - } - } - - return state; - } -} diff --git a/src/vs/platform/issue/common/issue.ts b/src/vs/platform/process/common/process.ts similarity index 52% rename from src/vs/platform/issue/common/issue.ts rename to src/vs/platform/process/common/process.ts index 3fc9e76e852..50f155da42c 100644 --- a/src/vs/platform/issue/common/issue.ts +++ b/src/vs/platform/process/common/process.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { UriComponents } from '../../../base/common/uri.js'; import { ISandboxConfiguration } from '../../../base/parts/sandbox/common/sandboxTypes.js'; import { PerformanceInfo, SystemInfo } from '../../diagnostics/common/diagnostics.js'; import { createDecorator } from '../../instantiation/common/instantiation.js'; @@ -19,68 +18,11 @@ export interface WindowData { zoomLevel: number; } -export const enum OldIssueType { - Bug, - PerformanceIssue, - FeatureRequest -} - export enum IssueSource { VSCode = 'vscode', Extension = 'extension', Marketplace = 'marketplace' } - -export interface OldIssueReporterStyles extends WindowStyles { - textLinkColor?: string; - textLinkActiveForeground?: string; - inputBackground?: string; - inputForeground?: string; - inputBorder?: string; - inputErrorBorder?: string; - inputErrorBackground?: string; - inputErrorForeground?: string; - inputActiveBorder?: string; - buttonBackground?: string; - buttonForeground?: string; - buttonHoverBackground?: string; - sliderBackgroundColor?: string; - sliderHoverColor?: string; - sliderActiveColor?: string; -} - -export interface OldIssueReporterExtensionData { - name: string; - publisher: string | undefined; - version: string; - id: string; - isTheme: boolean; - isBuiltin: boolean; - displayName: string | undefined; - repositoryUrl: string | undefined; - bugsUrl: string | undefined; - extensionData?: string; - extensionTemplate?: string; - data?: string; - uri?: UriComponents; -} - -export interface OldIssueReporterData extends WindowData { - styles: OldIssueReporterStyles; - enabledExtensions: OldIssueReporterExtensionData[]; - issueType?: OldIssueType; - issueSource?: IssueSource; - extensionId?: string; - experiments?: string; - restrictedMode: boolean; - isUnsupported: boolean; - githubAccessToken: string; - issueTitle?: string; - issueBody?: string; - data?: string; - uri?: UriComponents; -} - export interface ISettingSearchResult { extensionId: string; key: string; @@ -109,33 +51,10 @@ export interface ProcessExplorerData extends WindowData { applicationName: string; } -export interface OldIssueReporterWindowConfiguration extends ISandboxConfiguration { - disableExtensions: boolean; - data: OldIssueReporterData; - os: { - type: string; - arch: string; - release: string; - }; -} - export interface ProcessExplorerWindowConfiguration extends ISandboxConfiguration { data: ProcessExplorerData; } -export const IIssueMainService = createDecorator('issueService'); - -export interface IIssueMainService { - readonly _serviceBrand: undefined; - // Used by the issue reporter - openReporter(data: OldIssueReporterData): Promise; - $reloadWithExtensionsDisabled(): Promise; - $showConfirmCloseDialog(): Promise; - $showClipboardDialog(): Promise; - $sendReporterMenu(extensionId: string, extensionName: string): Promise; - $closeReporter(): Promise; -} - export const IProcessMainService = createDecorator('processService'); export interface IProcessMainService { diff --git a/src/vs/platform/issue/electron-main/processMainService.ts b/src/vs/platform/process/electron-main/processMainService.ts similarity index 99% rename from src/vs/platform/issue/electron-main/processMainService.ts rename to src/vs/platform/process/electron-main/processMainService.ts index bbf187a92b4..d2f6bbfd98a 100644 --- a/src/vs/platform/issue/electron-main/processMainService.ts +++ b/src/vs/platform/process/electron-main/processMainService.ts @@ -16,7 +16,7 @@ import { IDiagnosticsMainService } from '../../diagnostics/electron-main/diagnos import { IDialogMainService } from '../../dialogs/electron-main/dialogMainService.js'; import { IEnvironmentMainService } from '../../environment/electron-main/environmentMainService.js'; import { ICSSDevelopmentService } from '../../cssDev/node/cssDevService.js'; -import { IProcessMainService, ProcessExplorerData, ProcessExplorerWindowConfiguration } from '../common/issue.js'; +import { IProcessMainService, ProcessExplorerData, ProcessExplorerWindowConfiguration } from '../common/process.js'; import { ILogService } from '../../log/common/log.js'; import { INativeHostMainService } from '../../native/electron-main/nativeHostMainService.js'; import product from '../../product/common/product.js'; diff --git a/src/vs/workbench/contrib/issue/browser/baseIssueReporterService.ts b/src/vs/workbench/contrib/issue/browser/baseIssueReporterService.ts index 0fbc0b71baa..26d796b87f3 100644 --- a/src/vs/workbench/contrib/issue/browser/baseIssueReporterService.ts +++ b/src/vs/workbench/contrib/issue/browser/baseIssueReporterService.ts @@ -18,7 +18,6 @@ import { escape } from '../../../../base/common/strings.js'; import { ThemeIcon } from '../../../../base/common/themables.js'; import { URI } from '../../../../base/common/uri.js'; import { localize } from '../../../../nls.js'; -import { OldIssueReporterData } from '../../../../platform/issue/common/issue.js'; import { getIconsStyleSheet } from '../../../../platform/theme/browser/iconsStyleSheet.js'; import { IThemeService } from '../../../../platform/theme/common/themeService.js'; import { IssueReporterModel, IssueReporterData as IssueReporterModelData } from './issueReporterModel.js'; @@ -57,7 +56,7 @@ export class BaseIssueReporterService extends Disposable { constructor( public disableExtensions: boolean, - public data: IssueReporterData | OldIssueReporterData, + public data: IssueReporterData, public os: { type: string; arch: string; diff --git a/src/vs/workbench/contrib/issue/browser/issueReporterModel.ts b/src/vs/workbench/contrib/issue/browser/issueReporterModel.ts index 97d1199d1e6..0bbd8acf09a 100644 --- a/src/vs/workbench/contrib/issue/browser/issueReporterModel.ts +++ b/src/vs/workbench/contrib/issue/browser/issueReporterModel.ts @@ -5,11 +5,10 @@ import { mainWindow } from '../../../../base/browser/window.js'; import { isRemoteDiagnosticError, SystemInfo } from '../../../../platform/diagnostics/common/diagnostics.js'; -import { OldIssueType } from '../../../../platform/issue/common/issue.js'; import { ISettingSearchResult, IssueReporterExtensionData, IssueType } from '../common/issue.js'; export interface IssueReporterData { - issueType: IssueType | OldIssueType; + issueType: IssueType; issueDescription?: string; issueTitle?: string; extensionData?: string; diff --git a/src/vs/workbench/contrib/issue/browser/issueService.ts b/src/vs/workbench/contrib/issue/browser/issueService.ts index e0df98d0235..92cdd1bee2a 100644 --- a/src/vs/workbench/contrib/issue/browser/issueService.ts +++ b/src/vs/workbench/contrib/issue/browser/issueService.ts @@ -11,7 +11,7 @@ import { IConfigurationService } from '../../../../platform/configuration/common import { IExtensionManagementService } from '../../../../platform/extensionManagement/common/extensionManagement.js'; import { ExtensionType, IExtensionDescription } from '../../../../platform/extensions/common/extensions.js'; import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js'; -import { normalizeGitHubUrl } from '../../../../platform/issue/common/issueReporterUtil.js'; +import { normalizeGitHubUrl } from '../common/issueReporterUtil.js'; import { IProductService } from '../../../../platform/product/common/productService.js'; import { buttonBackground, buttonForeground, buttonHoverBackground, foreground, inputActiveOptionBorder, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, textLinkActiveForeground, textLinkForeground } from '../../../../platform/theme/common/colorRegistry.js'; import { IColorTheme, IThemeService } from '../../../../platform/theme/common/themeService.js'; diff --git a/src/vs/workbench/contrib/issue/common/issue.ts b/src/vs/workbench/contrib/issue/common/issue.ts index d0e970de5f1..f8f05bbb64d 100644 --- a/src/vs/workbench/contrib/issue/common/issue.ts +++ b/src/vs/workbench/contrib/issue/common/issue.ts @@ -6,7 +6,6 @@ import { UriComponents } from '../../../../base/common/uri.js'; import { ISandboxConfiguration } from '../../../../base/parts/sandbox/common/sandboxTypes.js'; import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js'; -import { OldIssueReporterData } from '../../../../platform/issue/common/issue.js'; // Since data sent through the service is serialized to JSON, functions will be lost, so Color objects // should not be sent as their 'toString' method will be stripped. Instead convert to strings before sending. @@ -109,16 +108,6 @@ export interface ProcessExplorerData extends WindowData { applicationName: string; } -export interface IssueReporterWindowConfiguration extends ISandboxConfiguration { - disableExtensions: boolean; - data: IssueReporterData | OldIssueReporterData; - os: { - type: string; - arch: string; - release: string; - }; -} - export interface ProcessExplorerWindowConfiguration extends ISandboxConfiguration { data: ProcessExplorerData; } diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/issue.contribution.ts b/src/vs/workbench/contrib/issue/electron-sandbox/issue.contribution.ts index 91a0f9b2706..4ff3e642e27 100644 --- a/src/vs/workbench/contrib/issue/electron-sandbox/issue.contribution.ts +++ b/src/vs/workbench/contrib/issue/electron-sandbox/issue.contribution.ts @@ -19,14 +19,11 @@ import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from '../.. import { IssueQuickAccess } from '../browser/issueQuickAccess.js'; import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js'; import { NativeIssueService } from './issueService.js'; -import './issueMainService.js'; +import './processMainService.js'; import '../browser/issueTroubleshoot.js'; -import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from '../../../../platform/configuration/common/configurationRegistry.js'; import { NativeIssueFormService } from './nativeIssueFormService.js'; - //#region Issue Contribution - registerSingleton(IWorkbenchIssueService, NativeIssueService, InstantiationType.Delayed); registerSingleton(IIssueFormService, NativeIssueFormService, InstantiationType.Delayed); @@ -57,16 +54,6 @@ class NativeIssueContribution extends BaseIssueContribution { }); }; - Registry.as(ConfigurationExtensions.Configuration).registerConfiguration({ - properties: { - 'issueReporter.experimental.auxWindow': { - type: 'boolean', - default: true, - description: 'Enable the new experimental issue reporter in electron.', - }, - } - }); - this._register(configurationService.onDidChangeConfiguration(e => { if (!configurationService.getValue('extensions.experimental.issueQuickAccess') && disposable) { disposable.dispose(); diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporter-dev.html b/src/vs/workbench/contrib/issue/electron-sandbox/issueReporter-dev.html deleted file mode 100644 index f14661a283c..00000000000 --- a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporter-dev.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporter.html b/src/vs/workbench/contrib/issue/electron-sandbox/issueReporter.html deleted file mode 100644 index 2f87d2489ce..00000000000 --- a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporter.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporter.ts b/src/vs/workbench/contrib/issue/electron-sandbox/issueReporter.ts deleted file mode 100644 index 629a6185ccb..00000000000 --- a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporter.ts +++ /dev/null @@ -1,26 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable no-restricted-globals */ - -(async function () { - - type IBootstrapWindow = import('vs/platform/window/electron-sandbox/window.js').IBootstrapWindow; - type IIssueReporterMain = import('vs/workbench/contrib/issue/electron-sandbox/issueReporterMain').IIssueReporterMain; - type OldIssueReporterWindowConfiguration = import('vs/platform/issue/common/issue.js').OldIssueReporterWindowConfiguration; - - const bootstrapWindow: IBootstrapWindow = (window as any).MonacoBootstrapWindow; // defined by bootstrap-window.ts - - const { result, configuration } = await bootstrapWindow.load('vs/workbench/contrib/issue/electron-sandbox/issueReporterMain', { - configureDeveloperSettings: function () { - return { - forceEnableDeveloperKeybindings: true, - disallowReloadKeybinding: true - }; - } - }); - - result.startup(configuration); -}()); diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterMain.ts b/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterMain.ts deleted file mode 100644 index fa1628e3be8..00000000000 --- a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterMain.ts +++ /dev/null @@ -1,57 +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 { safeInnerHtml } from '../../../../base/browser/dom.js'; -import '../../../../base/browser/ui/codicons/codiconStyles.js'; // make sure codicon css is loaded -import { mainWindow } from '../../../../base/browser/window.js'; -import { isLinux, isWindows } from '../../../../base/common/platform.js'; -import './media/issueReporter.css'; -import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js'; -import { getSingletonServiceDescriptors } from '../../../../platform/instantiation/common/extensions.js'; -import { InstantiationService } from '../../../../platform/instantiation/common/instantiationService.js'; -import { ServiceCollection } from '../../../../platform/instantiation/common/serviceCollection.js'; -import { IMainProcessService } from '../../../../platform/ipc/common/mainProcessService.js'; -import { ElectronIPCMainProcessService } from '../../../../platform/ipc/electron-sandbox/mainProcessService.js'; -import { registerMainProcessRemoteService } from '../../../../platform/ipc/electron-sandbox/services.js'; -import { INativeHostService } from '../../../../platform/native/common/native.js'; -import { NativeHostService } from '../../../../platform/native/common/nativeHostService.js'; -import BaseHtml from '../browser/issueReporterPage.js'; -import { IProcessMainService, IIssueMainService, OldIssueReporterWindowConfiguration } from '../../../../platform/issue/common/issue.js'; -import { IssueReporter } from './issueReporterService.js'; - -export interface IIssueReporterMain { - startup(configuration: OldIssueReporterWindowConfiguration): void; -} - -export function startup(configuration: OldIssueReporterWindowConfiguration): void { - const platformClass = isWindows ? 'windows' : isLinux ? 'linux' : 'mac'; - mainWindow.document.body.classList.add(platformClass); // used by our fonts - - safeInnerHtml(mainWindow.document.body, BaseHtml()); - - const instantiationService = initServices(configuration.windowId); - - const issueReporter = instantiationService.createInstance(IssueReporter, configuration); - issueReporter.render(); - mainWindow.document.body.style.display = 'block'; - issueReporter.setInitialFocus(); -} - -function initServices(windowId: number) { - const services = new ServiceCollection(); - - const contributedServices = getSingletonServiceDescriptors(); - for (const [id, descriptor] of contributedServices) { - services.set(id, descriptor); - } - - services.set(IMainProcessService, new SyncDescriptor(ElectronIPCMainProcessService, [windowId])); - services.set(INativeHostService, new SyncDescriptor(NativeHostService, [windowId])); - - return new InstantiationService(services, true); -} - -registerMainProcessRemoteService(IIssueMainService, 'issue'); -registerMainProcessRemoteService(IProcessMainService, 'process'); diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService.ts b/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService.ts index bc6f5eb9de2..5232574fab6 100644 --- a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService.ts +++ b/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService.ts @@ -2,112 +2,44 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { $, createStyleSheet, isHTMLInputElement, isHTMLTextAreaElement, reset, windowOpenNoOpener } from '../../../../base/browser/dom.js'; -import { Button, unthemedButtonStyles } from '../../../../base/browser/ui/button/button.js'; -import { renderIcon } from '../../../../base/browser/ui/iconLabel/iconLabels.js'; -import { mainWindow } from '../../../../base/browser/window.js'; -import { Delayer, RunOnceScheduler } from '../../../../base/common/async.js'; -import { Codicon } from '../../../../base/common/codicons.js'; -import { groupBy } from '../../../../base/common/collections.js'; -import { debounce } from '../../../../base/common/decorators.js'; +import { $, reset } from '../../../../base/browser/dom.js'; import { CancellationError } from '../../../../base/common/errors.js'; -import { Disposable } from '../../../../base/common/lifecycle.js'; -import { isLinuxSnap, isMacintosh } from '../../../../base/common/platform.js'; -import { escape } from '../../../../base/common/strings.js'; -import { ThemeIcon } from '../../../../base/common/themables.js'; +import { IProductConfiguration } from '../../../../base/common/product.js'; import { URI } from '../../../../base/common/uri.js'; import { localize } from '../../../../nls.js'; import { isRemoteDiagnosticError } from '../../../../platform/diagnostics/common/diagnostics.js'; -import { IIssueMainService, IProcessMainService, OldIssueReporterData, OldIssueReporterExtensionData, OldIssueReporterStyles, OldIssueReporterWindowConfiguration, OldIssueType } from '../../../../platform/issue/common/issue.js'; +import { IProcessMainService } from '../../../../platform/process/common/process.js'; import { INativeHostService } from '../../../../platform/native/common/native.js'; -import { getIconsStyleSheet } from '../../../../platform/theme/browser/iconsStyleSheet.js'; -import { applyZoom, zoomIn, zoomOut } from '../../../../platform/window/electron-sandbox/window.js'; -import { IssueReporterData, IssueReporterModel, IssueReporterData as IssueReporterModelData } from '../browser/issueReporterModel.js'; -import { normalizeGitHubUrl } from '../common/issueReporterUtil.js'; +import { IThemeService } from '../../../../platform/theme/common/themeService.js'; +import { applyZoom } from '../../../../platform/window/electron-sandbox/window.js'; +import { BaseIssueReporterService } from '../browser/baseIssueReporterService.js'; +import { IssueReporterData as IssueReporterModelData } from '../browser/issueReporterModel.js'; +import { IIssueFormService, IssueReporterData, IssueType } from '../common/issue.js'; // 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 const MAX_URL_LENGTH = 7500; -interface SearchResult { - html_url: string; - title: string; - state?: string; -} - -enum IssueSource { - VSCode = 'vscode', - Extension = 'extension', - Marketplace = 'marketplace', - Unknown = 'unknown' -} - -export class IssueReporter extends Disposable { - private readonly issueReporterModel: IssueReporterModel; - private numberOfSearchResultsDisplayed = 0; - private receivedSystemInfo = false; - private receivedPerformanceInfo = false; - private shouldQueueSearch = false; - private hasBeenSubmitted = false; - private openReporter = false; - private loadingExtensionData = false; - private selectedExtension = ''; - private delayedSubmit = new Delayer(300); - private readonly previewButton!: Button; - private nonGitHubIssueUrl = false; +export class IssueReporter extends BaseIssueReporterService { + private readonly processMainService: IProcessMainService; constructor( - private readonly configuration: OldIssueReporterWindowConfiguration, + disableExtensions: boolean, + data: IssueReporterData, + os: { + type: string; + arch: string; + release: string; + }, + product: IProductConfiguration, + window: Window, @INativeHostService private readonly nativeHostService: INativeHostService, - @IIssueMainService private readonly issueMainService: IIssueMainService, - @IProcessMainService private readonly processMainService: IProcessMainService + @IIssueFormService issueFormService: IIssueFormService, + @IProcessMainService processMainService: IProcessMainService, + @IThemeService themeService: IThemeService ) { - super(); - const targetExtension = configuration.data.extensionId ? configuration.data.enabledExtensions.find(extension => extension.id.toLocaleLowerCase() === configuration.data.extensionId?.toLocaleLowerCase()) : undefined; - this.issueReporterModel = new IssueReporterModel({ - ...configuration.data, - issueType: configuration.data.issueType || OldIssueType.Bug, - versionInfo: { - vscodeVersion: `${configuration.product.nameShort} ${!!configuration.product.darwinUniversalAssetId ? `${configuration.product.version} (Universal)` : configuration.product.version} (${configuration.product.commit || 'Commit unknown'}, ${configuration.product.date || 'Date unknown'})`, - os: `${this.configuration.os.type} ${this.configuration.os.arch} ${this.configuration.os.release}${isLinuxSnap ? ' snap' : ''}` - }, - extensionsDisabled: !!configuration.disableExtensions, - fileOnExtension: configuration.data.extensionId ? !targetExtension?.isBuiltin : undefined, - selectedExtension: targetExtension - }); - - const fileOnMarketplace = configuration.data.issueSource === IssueSource.Marketplace; - const fileOnProduct = configuration.data.issueSource === IssueSource.VSCode; - this.issueReporterModel.update({ fileOnMarketplace, fileOnProduct }); - - //TODO: Handle case where extension is not activated - const issueReporterElement = this.getElementById('issue-reporter'); - if (issueReporterElement) { - this.previewButton = new Button(issueReporterElement, unthemedButtonStyles); - const issueRepoName = document.createElement('a'); - issueReporterElement.appendChild(issueRepoName); - issueRepoName.id = 'show-repo-name'; - issueRepoName.classList.add('hidden'); - this.updatePreviewButtonState(); - } - - const issueTitle = configuration.data.issueTitle; - if (issueTitle) { - const issueTitleElement = this.getElementById('issue-title'); - if (issueTitleElement) { - issueTitleElement.value = issueTitle; - } - } - - const issueBody = configuration.data.issueBody; - if (issueBody) { - const description = this.getElementById('description'); - if (description) { - description.value = issueBody; - this.issueReporterModel.update({ issueDescription: issueBody }); - } - } - + super(disableExtensions, data, os, product, window, false, issueFormService, themeService); + this.processMainService = processMainService; this.processMainService.$getSystemInfo().then(info => { this.issueReporterModel.update({ systemInfo: info }); this.receivedSystemInfo = true; @@ -115,178 +47,26 @@ export class IssueReporter extends Disposable { this.updateSystemInfo(this.issueReporterModel.getData()); this.updatePreviewButtonState(); }); - if (configuration.data.issueType === OldIssueType.PerformanceIssue) { + if (this.data.issueType === IssueType.PerformanceIssue) { this.processMainService.$getPerformanceInfo().then(info => { this.updatePerformanceInfo(info as Partial); }); } - if (mainWindow.document.documentElement.lang !== 'en') { - show(this.getElementById('english')); - } - - const codiconStyleSheet = createStyleSheet(); - codiconStyleSheet.id = 'codiconStyles'; - - // TODO: Is there a way to use the IThemeService here instead - const iconsStyleSheet = this._register(getIconsStyleSheet(undefined)); - function updateAll() { - codiconStyleSheet.textContent = iconsStyleSheet.getCSS(); - } - - const delayer = new RunOnceScheduler(updateAll, 0); - iconsStyleSheet.onDidChange(() => delayer.schedule()); - delayer.schedule(); - - this.setUpTypes(); this.setEventHandlers(); - applyZoom(configuration.data.zoomLevel, mainWindow); - this.applyStyles(configuration.data.styles); - this.handleExtensionData(configuration.data.enabledExtensions); - this.updateExperimentsInfo(configuration.data.experiments); - this.updateRestrictedMode(configuration.data.restrictedMode); - this.updateUnsupportedMode(configuration.data.isUnsupported); - - // Handle case where extension is pre-selected through the command - if ((configuration.data.data || configuration.data.uri) && targetExtension) { - this.updateExtensionStatus(targetExtension); - } + applyZoom(this.data.zoomLevel, this.window); + this.updateExperimentsInfo(this.data.experiments); + this.updateRestrictedMode(this.data.restrictedMode); + this.updateUnsupportedMode(this.data.isUnsupported); } - render(): void { - this.renderBlocks(); - } + public override setEventHandlers(): void { + super.setEventHandlers(); - setInitialFocus() { - const { fileOnExtension } = this.issueReporterModel.getData(); - if (fileOnExtension) { - const issueTitle = mainWindow.document.getElementById('issue-title'); - issueTitle?.focus(); - } else { - const issueType = mainWindow.document.getElementById('issue-type'); - issueType?.focus(); - } - } - - // TODO @justschen: After migration to Aux Window, switch to dedicated css. - private applyStyles(styles: OldIssueReporterStyles) { - const styleTag = document.createElement('style'); - const content: string[] = []; - - if (styles.inputBackground) { - content.push(`input[type="text"], textarea, select, .issues-container > .issue > .issue-state, .block-info { background-color: ${styles.inputBackground}; }`); - } - - if (styles.inputBorder) { - content.push(`input[type="text"], textarea, select { border: 1px solid ${styles.inputBorder}; }`); - } else { - content.push(`input[type="text"], textarea, select { border: 1px solid transparent; }`); - } - - if (styles.inputForeground) { - content.push(`input[type="text"], textarea, select, .issues-container > .issue > .issue-state, .block-info { color: ${styles.inputForeground}; }`); - } - - if (styles.inputErrorBorder) { - content.push(`.invalid-input, .invalid-input:focus, .validation-error { border: 1px solid ${styles.inputErrorBorder} !important; }`); - content.push(`.required-input { color: ${styles.inputErrorBorder}; }`); - } - - if (styles.inputErrorBackground) { - content.push(`.validation-error { background: ${styles.inputErrorBackground}; }`); - } - - if (styles.inputErrorForeground) { - content.push(`.validation-error { color: ${styles.inputErrorForeground}; }`); - } - - if (styles.inputActiveBorder) { - content.push(`input[type='text']:focus, textarea:focus, select:focus, summary:focus, button:focus, a:focus, .workbenchCommand:focus { border: 1px solid ${styles.inputActiveBorder}; outline-style: none; }`); - } - - if (styles.textLinkColor) { - content.push(`a, .workbenchCommand { color: ${styles.textLinkColor}; }`); - } - - if (styles.textLinkColor) { - content.push(`a { color: ${styles.textLinkColor}; }`); - } - - if (styles.textLinkActiveForeground) { - content.push(`a:hover, .workbenchCommand:hover { color: ${styles.textLinkActiveForeground}; }`); - } - - if (styles.sliderBackgroundColor) { - content.push(`::-webkit-scrollbar-thumb { background-color: ${styles.sliderBackgroundColor}; }`); - } - - if (styles.sliderActiveColor) { - content.push(`::-webkit-scrollbar-thumb:active { background-color: ${styles.sliderActiveColor}; }`); - } - - if (styles.sliderHoverColor) { - content.push(`::--webkit-scrollbar-thumb:hover { background-color: ${styles.sliderHoverColor}; }`); - } - - if (styles.buttonBackground) { - content.push(`.monaco-text-button { background-color: ${styles.buttonBackground} !important; }`); - } - - if (styles.buttonForeground) { - content.push(`.monaco-text-button { color: ${styles.buttonForeground} !important; }`); - } - - if (styles.buttonHoverBackground) { - content.push(`.monaco-text-button:not(.disabled):hover, .monaco-text-button:focus { background-color: ${styles.buttonHoverBackground} !important; }`); - } - - styleTag.textContent = content.join('\n'); - mainWindow.document.head.appendChild(styleTag); - mainWindow.document.body.style.color = styles.color || ''; - } - - private handleExtensionData(extensions: OldIssueReporterExtensionData[]) { - const installedExtensions = extensions.filter(x => !x.isBuiltin); - const { nonThemes, themes } = groupBy(installedExtensions, ext => { - return ext.isTheme ? 'themes' : 'nonThemes'; - }); - - const numberOfThemeExtesions = themes && themes.length; - this.issueReporterModel.update({ numberOfThemeExtesions, enabledNonThemeExtesions: nonThemes, allExtensions: installedExtensions }); - this.updateExtensionTable(nonThemes, numberOfThemeExtesions); - if (this.configuration.disableExtensions || installedExtensions.length === 0) { - (this.getElementById('disableExtensions')).disabled = true; - } - - this.updateExtensionSelector(installedExtensions); - } - - private async updateIssueReporterUri(extension: OldIssueReporterExtensionData): Promise { - try { - if (extension.uri) { - const uri = URI.revive(extension.uri); - extension.bugsUrl = uri.toString(); - } - } catch (e) { - this.renderBlocks(); - } - } - - private async sendReporterMenu(extension: OldIssueReporterExtensionData): Promise { - try { - const data = await this.issueMainService.$sendReporterMenu(extension.id, extension.name); - return data; - } catch (e) { - console.error(e); - return undefined; - } - } - - private setEventHandlers(): void { this.addEventListener('issue-type', 'change', (event: Event) => { const issueType = parseInt((event.target).value); this.issueReporterModel.update({ issueType: issueType }); - if (issueType === OldIssueType.PerformanceIssue && !this.receivedPerformanceInfo) { + if (issueType === IssueType.PerformanceIssue && !this.receivedPerformanceInfo) { this.processMainService.$getPerformanceInfo().then(info => { this.updatePerformanceInfo(info as Partial); }); @@ -302,630 +82,9 @@ export class IssueReporter extends Disposable { this.setSourceOptions(); this.render(); }); - - (['includeSystemInfo', 'includeProcessInfo', 'includeWorkspaceInfo', 'includeExtensions', 'includeExperiments', 'includeExtensionData'] as const).forEach(elementId => { - this.addEventListener(elementId, 'click', (event: Event) => { - event.stopPropagation(); - this.issueReporterModel.update({ [elementId]: !this.issueReporterModel.getData()[elementId] }); - }); - }); - - const showInfoElements = mainWindow.document.getElementsByClassName('showInfo'); - for (let i = 0; i < showInfoElements.length; i++) { - const showInfo = showInfoElements.item(i)!; - (showInfo as HTMLAnchorElement).addEventListener('click', (e: MouseEvent) => { - e.preventDefault(); - const label = (e.target); - if (label) { - const containingElement = label.parentElement && label.parentElement.parentElement; - const info = containingElement && containingElement.lastElementChild; - if (info && info.classList.contains('hidden')) { - show(info); - label.textContent = localize('hide', "hide"); - } else { - hide(info); - label.textContent = localize('show', "show"); - } - } - }); - } - - this.addEventListener('issue-source', 'change', (e: Event) => { - const value = (e.target).value; - const problemSourceHelpText = this.getElementById('problem-source-help-text')!; - if (value === '') { - this.issueReporterModel.update({ fileOnExtension: undefined }); - show(problemSourceHelpText); - this.clearSearchResults(); - this.render(); - return; - } else { - hide(problemSourceHelpText); - } - - const descriptionTextArea = this.getElementById('issue-title'); - if (value === IssueSource.VSCode) { - descriptionTextArea.placeholder = localize('vscodePlaceholder', "E.g Workbench is missing problems panel"); - } else if (value === IssueSource.Extension) { - descriptionTextArea.placeholder = localize('extensionPlaceholder', "E.g. Missing alt text on extension readme image"); - } else if (value === IssueSource.Marketplace) { - descriptionTextArea.placeholder = localize('marketplacePlaceholder', "E.g Cannot disable installed extension"); - } else { - descriptionTextArea.placeholder = localize('undefinedPlaceholder', "Please enter a title"); - } - - let fileOnExtension, fileOnMarketplace = false; - if (value === IssueSource.Extension) { - fileOnExtension = true; - } else if (value === IssueSource.Marketplace) { - fileOnMarketplace = true; - } - - this.issueReporterModel.update({ fileOnExtension, fileOnMarketplace }); - this.render(); - - const title = (this.getElementById('issue-title')).value; - this.searchIssues(title, fileOnExtension, fileOnMarketplace); - }); - - this.addEventListener('description', 'input', (e: Event) => { - const issueDescription = (e.target).value; - this.issueReporterModel.update({ issueDescription }); - - // Only search for extension issues on title change - if (this.issueReporterModel.fileOnExtension() === false) { - const title = (this.getElementById('issue-title')).value; - this.searchVSCodeIssues(title, issueDescription); - } - }); - - this.addEventListener('issue-title', 'input', (e: Event) => { - const title = (e.target).value; - const lengthValidationMessage = this.getElementById('issue-title-length-validation-error'); - const issueUrl = this.getIssueUrl(); - if (title && this.getIssueUrlWithTitle(title, issueUrl).length > MAX_URL_LENGTH) { - show(lengthValidationMessage); - } else { - hide(lengthValidationMessage); - } - const issueSource = this.getElementById('issue-source'); - if (!issueSource || issueSource.value === '') { - return; - } - - const { fileOnExtension, fileOnMarketplace } = this.issueReporterModel.getData(); - this.searchIssues(title, fileOnExtension, fileOnMarketplace); - }); - - this.previewButton.onDidClick(async () => { - this.delayedSubmit.trigger(async () => { - this.createIssue(); - }); - }); - - this.addEventListener('disableExtensions', 'click', () => { - this.issueMainService.$reloadWithExtensionsDisabled(); - }); - - this.addEventListener('extensionBugsLink', 'click', (e: Event) => { - const url = (e.target).innerText; - windowOpenNoOpener(url); - }); - - this.addEventListener('disableExtensions', 'keydown', (e: Event) => { - e.stopPropagation(); - if ((e as KeyboardEvent).keyCode === 13 || (e as KeyboardEvent).keyCode === 32) { - this.issueMainService.$reloadWithExtensionsDisabled(); - } - }); - - mainWindow.document.onkeydown = async (e: KeyboardEvent) => { - const cmdOrCtrlKey = isMacintosh ? e.metaKey : e.ctrlKey; - // Cmd/Ctrl+Enter previews issue and closes window - if (cmdOrCtrlKey && e.keyCode === 13) { - this.delayedSubmit.trigger(async () => { - if (await this.createIssue()) { - this.close(); - } - }); - } - - // Cmd/Ctrl + w closes issue window - if (cmdOrCtrlKey && e.keyCode === 87) { - e.stopPropagation(); - e.preventDefault(); - - const issueTitle = (this.getElementById('issue-title'))!.value; - const { issueDescription } = this.issueReporterModel.getData(); - if (!this.hasBeenSubmitted && (issueTitle || issueDescription)) { - // fire and forget - this.issueMainService.$showConfirmCloseDialog(); - } else { - this.close(); - } - } - - // Cmd/Ctrl + zooms in - if (cmdOrCtrlKey && e.keyCode === 187) { - zoomIn(mainWindow); - } - - // Cmd/Ctrl - zooms out - if (cmdOrCtrlKey && e.keyCode === 189) { - zoomOut(mainWindow); - } - - // With latest electron upgrade, cmd+a is no longer propagating correctly for inputs in this window on mac - // Manually perform the selection - if (isMacintosh) { - if (cmdOrCtrlKey && e.keyCode === 65 && e.target) { - if (isHTMLInputElement(e.target) || isHTMLTextAreaElement(e.target)) { - (e.target).select(); - } - } - } - }; } - private updatePerformanceInfo(info: Partial) { - this.issueReporterModel.update(info); - this.receivedPerformanceInfo = true; - - const state = this.issueReporterModel.getData(); - this.updateProcessInfo(state); - this.updateWorkspaceInfo(state); - this.updatePreviewButtonState(); - } - - private updatePreviewButtonState() { - if (this.isPreviewEnabled()) { - if (this.configuration.data.githubAccessToken) { - this.previewButton.label = localize('createOnGitHub', "Create on GitHub"); - } else { - this.previewButton.label = localize('previewOnGitHub', "Preview on GitHub"); - } - this.previewButton.enabled = true; - } else { - this.previewButton.enabled = false; - this.previewButton.label = localize('loadingData', "Loading data..."); - } - - const issueRepoName = this.getElementById('show-repo-name')! as HTMLAnchorElement; - const selectedExtension = this.issueReporterModel.getData().selectedExtension; - if (selectedExtension && selectedExtension.uri) { - const urlString = URI.revive(selectedExtension.uri).toString(); - issueRepoName.href = urlString; - issueRepoName.addEventListener('click', (e) => this.openLink(e)); - issueRepoName.addEventListener('auxclick', (e) => this.openLink(e)); - const gitHubInfo = this.parseGitHubUrl(urlString); - issueRepoName.textContent = gitHubInfo ? gitHubInfo.owner + '/' + gitHubInfo.repositoryName : urlString; - Object.assign(issueRepoName.style, { - alignSelf: 'flex-end', - display: 'block', - fontSize: '13px', - marginBottom: '10px', - padding: '4px 0px', - textDecoration: 'none', - width: 'auto' - }); - show(issueRepoName); - } else { - // clear styles - issueRepoName.removeAttribute('style'); - hide(issueRepoName); - } - - // Initial check when first opened. - this.getExtensionGitHubUrl(); - } - - private isPreviewEnabled() { - const issueType = this.issueReporterModel.getData().issueType; - - if (this.loadingExtensionData) { - return false; - } - - if (issueType === OldIssueType.Bug && this.receivedSystemInfo) { - return true; - } - - if (issueType === OldIssueType.PerformanceIssue && this.receivedSystemInfo && this.receivedPerformanceInfo) { - return true; - } - - if (issueType === OldIssueType.FeatureRequest) { - return true; - } - - return false; - } - - private getExtensionRepositoryUrl(): string | undefined { - const selectedExtension = this.issueReporterModel.getData().selectedExtension; - return selectedExtension && selectedExtension.repositoryUrl; - } - - private getExtensionBugsUrl(): string | undefined { - const selectedExtension = this.issueReporterModel.getData().selectedExtension; - return selectedExtension && selectedExtension.bugsUrl; - } - - private searchVSCodeIssues(title: string, issueDescription?: string): void { - if (title) { - this.searchDuplicates(title, issueDescription); - } else { - this.clearSearchResults(); - } - } - - private searchIssues(title: string, fileOnExtension: boolean | undefined, fileOnMarketplace: boolean | undefined): void { - if (fileOnExtension) { - return this.searchExtensionIssues(title); - } - - if (fileOnMarketplace) { - return this.searchMarketplaceIssues(title); - } - - const description = this.issueReporterModel.getData().issueDescription; - this.searchVSCodeIssues(title, description); - } - - private searchExtensionIssues(title: string): void { - const url = this.getExtensionGitHubUrl(); - if (title) { - const matches = /^https?:\/\/github\.com\/(.*)/.exec(url); - if (matches && matches.length) { - const repo = matches[1]; - return this.searchGitHub(repo, title); - } - - // If the extension has no repository, display empty search results - if (this.issueReporterModel.getData().selectedExtension) { - this.clearSearchResults(); - return this.displaySearchResults([]); - - } - } - - this.clearSearchResults(); - } - - private searchMarketplaceIssues(title: string): void { - if (title) { - const gitHubInfo = this.parseGitHubUrl(this.configuration.product.reportMarketplaceIssueUrl!); - if (gitHubInfo) { - return this.searchGitHub(`${gitHubInfo.owner}/${gitHubInfo.repositoryName}`, title); - } - } - } - - private async close(): Promise { - await this.issueMainService.$closeReporter(); - } - - private clearSearchResults(): void { - const similarIssues = this.getElementById('similar-issues')!; - similarIssues.innerText = ''; - this.numberOfSearchResultsDisplayed = 0; - } - - @debounce(300) - private searchGitHub(repo: string, title: string): void { - const query = `is:issue+repo:${repo}+${title}`; - const similarIssues = this.getElementById('similar-issues')!; - - fetch(`https://api.github.com/search/issues?q=${query}`).then((response) => { - response.json().then(result => { - similarIssues.innerText = ''; - if (result && result.items) { - this.displaySearchResults(result.items); - } else { - // If the items property isn't present, the rate limit has been hit - const message = $('div.list-title'); - message.textContent = localize('rateLimited', "GitHub query limit exceeded. Please wait."); - similarIssues.appendChild(message); - - const resetTime = response.headers.get('X-RateLimit-Reset'); - const timeToWait = resetTime ? parseInt(resetTime) - Math.floor(Date.now() / 1000) : 1; - if (this.shouldQueueSearch) { - this.shouldQueueSearch = false; - setTimeout(() => { - this.searchGitHub(repo, title); - this.shouldQueueSearch = true; - }, timeToWait * 1000); - } - } - }).catch(_ => { - // Ignore - }); - }).catch(_ => { - // Ignore - }); - } - - @debounce(300) - private searchDuplicates(title: string, body?: string): void { - const url = 'https://vscode-probot.westus.cloudapp.azure.com:7890/duplicate_candidates'; - const init = { - method: 'POST', - body: JSON.stringify({ - title, - body - }), - headers: new Headers({ - 'Content-Type': 'application/json' - }) - }; - - fetch(url, init).then((response) => { - response.json().then(result => { - this.clearSearchResults(); - - if (result && result.candidates) { - this.displaySearchResults(result.candidates); - } else { - throw new Error('Unexpected response, no candidates property'); - } - }).catch(_ => { - // Ignore - }); - }).catch(_ => { - // Ignore - }); - } - - private displaySearchResults(results: SearchResult[]) { - const similarIssues = this.getElementById('similar-issues')!; - if (results.length) { - const issues = $('div.issues-container'); - const issuesText = $('div.list-title'); - issuesText.textContent = localize('similarIssues', "Similar issues"); - - this.numberOfSearchResultsDisplayed = results.length < 5 ? results.length : 5; - for (let i = 0; i < this.numberOfSearchResultsDisplayed; i++) { - const issue = results[i]; - const link = $('a.issue-link', { href: issue.html_url }); - link.textContent = issue.title; - link.title = issue.title; - link.addEventListener('click', (e) => this.openLink(e)); - link.addEventListener('auxclick', (e) => this.openLink(e)); - - let issueState: HTMLElement; - let item: HTMLElement; - if (issue.state) { - issueState = $('span.issue-state'); - - const issueIcon = $('span.issue-icon'); - issueIcon.appendChild(renderIcon(issue.state === 'open' ? Codicon.issueOpened : Codicon.issueClosed)); - - const issueStateLabel = $('span.issue-state.label'); - issueStateLabel.textContent = issue.state === 'open' ? localize('open', "Open") : localize('closed', "Closed"); - - issueState.title = issue.state === 'open' ? localize('open', "Open") : localize('closed', "Closed"); - issueState.appendChild(issueIcon); - issueState.appendChild(issueStateLabel); - - item = $('div.issue', undefined, issueState, link); - } else { - item = $('div.issue', undefined, link); - } - - issues.appendChild(item); - } - - similarIssues.appendChild(issuesText); - similarIssues.appendChild(issues); - } else { - const message = $('div.list-title'); - message.textContent = localize('noSimilarIssues', "No similar issues found"); - similarIssues.appendChild(message); - } - } - - private setUpTypes(): void { - const makeOption = (issueType: OldIssueType, description: string) => $('option', { 'value': issueType.valueOf() }, escape(description)); - - const typeSelect = this.getElementById('issue-type')! as HTMLSelectElement; - const { issueType } = this.issueReporterModel.getData(); - reset(typeSelect, - makeOption(OldIssueType.Bug, localize('bugReporter', "Bug Report")), - makeOption(OldIssueType.FeatureRequest, localize('featureRequest', "Feature Request")), - makeOption(OldIssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue (freeze, slow, crash)")) - ); - - typeSelect.value = issueType.toString(); - - this.setSourceOptions(); - } - - private makeOption(value: string, description: string, disabled: boolean): HTMLOptionElement { - const option: HTMLOptionElement = document.createElement('option'); - option.disabled = disabled; - option.value = value; - option.textContent = description; - - return option; - } - - private setSourceOptions(): void { - const sourceSelect = this.getElementById('issue-source')! as HTMLSelectElement; - const { issueType, fileOnExtension, selectedExtension, fileOnMarketplace, fileOnProduct } = this.issueReporterModel.getData(); - let selected = sourceSelect.selectedIndex; - if (selected === -1) { - if (fileOnExtension !== undefined) { - selected = fileOnExtension ? 2 : 1; - } else if (selectedExtension?.isBuiltin) { - selected = 1; - } else if (fileOnMarketplace) { - selected = 3; - } else if (fileOnProduct) { - selected = 1; - } - } - - sourceSelect.innerText = ''; - sourceSelect.append(this.makeOption('', localize('selectSource', "Select source"), true)); - sourceSelect.append(this.makeOption(IssueSource.VSCode, localize('vscode', "Visual Studio Code"), false)); - sourceSelect.append(this.makeOption(IssueSource.Extension, localize('extension', "A VS Code extension"), false)); - if (this.configuration.product.reportMarketplaceIssueUrl) { - sourceSelect.append(this.makeOption(IssueSource.Marketplace, localize('marketplace', "Extensions Marketplace"), false)); - } - - if (issueType !== OldIssueType.FeatureRequest) { - sourceSelect.append(this.makeOption(IssueSource.Unknown, localize('unknown', "Don't know"), false)); - } - - if (selected !== -1 && selected < sourceSelect.options.length) { - sourceSelect.selectedIndex = selected; - } else { - sourceSelect.selectedIndex = 0; - hide(this.getElementById('problem-source-help-text')); - } - } - - private renderBlocks(): void { - // Depending on Issue Type, we render different blocks and text - const { issueType, fileOnExtension, fileOnMarketplace, selectedExtension } = this.issueReporterModel.getData(); - const blockContainer = this.getElementById('block-container'); - const systemBlock = mainWindow.document.querySelector('.block-system'); - const processBlock = mainWindow.document.querySelector('.block-process'); - const workspaceBlock = mainWindow.document.querySelector('.block-workspace'); - const extensionsBlock = mainWindow.document.querySelector('.block-extensions'); - const experimentsBlock = mainWindow.document.querySelector('.block-experiments'); - const extensionDataBlock = mainWindow.document.querySelector('.block-extension-data'); - - const problemSource = this.getElementById('problem-source')!; - const descriptionTitle = this.getElementById('issue-description-label')!; - const descriptionSubtitle = this.getElementById('issue-description-subtitle')!; - const extensionSelector = this.getElementById('extension-selection')!; - - const titleTextArea = this.getElementById('issue-title-container')!; - const descriptionTextArea = this.getElementById('description')!; - const extensionDataTextArea = this.getElementById('extension-data')!; - - // Hide all by default - hide(blockContainer); - hide(systemBlock); - hide(processBlock); - hide(workspaceBlock); - hide(extensionsBlock); - hide(experimentsBlock); - hide(extensionSelector); - hide(extensionDataTextArea); - hide(extensionDataBlock); - - show(problemSource); - show(titleTextArea); - show(descriptionTextArea); - - if (fileOnExtension) { - show(extensionSelector); - } - - - if (selectedExtension && this.nonGitHubIssueUrl) { - hide(titleTextArea); - hide(descriptionTextArea); - reset(descriptionTitle, localize('handlesIssuesElsewhere', "This extension handles issues outside of VS Code")); - reset(descriptionSubtitle, localize('elsewhereDescription', "The '{0}' extension prefers to use an external issue reporter. To be taken to that issue reporting experience, click the button below.", selectedExtension.displayName)); - this.previewButton.label = localize('openIssueReporter', "Open External Issue Reporter"); - return; - } - - if (fileOnExtension && selectedExtension?.data) { - const data = selectedExtension?.data; - (extensionDataTextArea as HTMLElement).innerText = data.toString(); - (extensionDataTextArea as HTMLTextAreaElement).readOnly = true; - show(extensionDataBlock); - } - - // only if we know comes from the open reporter command - if (fileOnExtension && this.openReporter) { - (extensionDataTextArea as HTMLTextAreaElement).readOnly = true; - setTimeout(() => { - // delay to make sure from command or not - if (this.openReporter) { - show(extensionDataBlock); - } - }, 100); - } - - if (issueType === OldIssueType.Bug) { - if (!fileOnMarketplace) { - show(blockContainer); - show(systemBlock); - show(experimentsBlock); - if (!fileOnExtension) { - show(extensionsBlock); - } - } - - reset(descriptionTitle, localize('stepsToReproduce', "Steps to Reproduce") + ' ', $('span.required-input', undefined, '*')); - reset(descriptionSubtitle, localize('bugDescription', "Share the steps needed to reliably reproduce the problem. Please include actual and expected results. 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 === OldIssueType.PerformanceIssue) { - if (!fileOnMarketplace) { - show(blockContainer); - show(systemBlock); - show(processBlock); - show(workspaceBlock); - show(experimentsBlock); - } - - if (fileOnExtension) { - show(extensionSelector); - } else if (!fileOnMarketplace) { - show(extensionsBlock); - } - - reset(descriptionTitle, localize('stepsToReproduce', "Steps to Reproduce") + ' ', $('span.required-input', undefined, '*')); - reset(descriptionSubtitle, 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 if (issueType === OldIssueType.FeatureRequest) { - reset(descriptionTitle, localize('description', "Description") + ' ', $('span.required-input', undefined, '*')); - reset(descriptionSubtitle, 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.")); - } - } - - private validateInput(inputId: string): boolean { - const inputElement = (this.getElementById(inputId)); - const inputValidationMessage = this.getElementById(`${inputId}-empty-error`); - const descriptionShortMessage = this.getElementById(`description-short-error`); - if (!inputElement.value) { - inputElement.classList.add('invalid-input'); - inputValidationMessage?.classList.remove('hidden'); - descriptionShortMessage?.classList.add('hidden'); - return false; - } else if (inputId === 'description' && inputElement.value.length < 10) { - inputElement.classList.add('invalid-input'); - descriptionShortMessage?.classList.remove('hidden'); - inputValidationMessage?.classList.add('hidden'); - return false; - } - else { - inputElement.classList.remove('invalid-input'); - inputValidationMessage?.classList.add('hidden'); - if (inputId === 'description') { - descriptionShortMessage?.classList.add('hidden'); - } - return true; - } - } - - private validateInputs(): boolean { - let isValid = true; - ['issue-title', 'description', 'issue-source'].forEach(elementId => { - isValid = this.validateInput(elementId) && isValid; - }); - - if (this.issueReporterModel.fileOnExtension()) { - isValid = this.validateInput('extension-selector') && isValid; - } - - return isValid; - } - - private async submitToGitHub(issueTitle: string, issueBody: string, gitHubDetails: { owner: string; repositoryName: string }): Promise { + public override async submitToGitHub(issueTitle: string, issueBody: string, gitHubDetails: { owner: string; repositoryName: string }): Promise { const url = `https://api.github.com/repos/${gitHubDetails.owner}/${gitHubDetails.repositoryName}/issues`; const init = { method: 'POST', @@ -935,7 +94,7 @@ export class IssueReporter extends Disposable { }), headers: new Headers({ 'Content-Type': 'application/json', - 'Authorization': `Bearer ${this.configuration.data.githubAccessToken}` + 'Authorization': `Bearer ${this.data.githubAccessToken}` }) }; @@ -950,7 +109,7 @@ export class IssueReporter extends Disposable { return true; } - private async createIssue(): Promise { + public override async createIssue(): Promise { const selectedExtension = this.issueReporterModel.getData().selectedExtension; const hasUri = this.nonGitHubIssueUrl; // Short circuit if the extension provides a custom issue handler @@ -966,7 +125,7 @@ export class IssueReporter extends Disposable { if (!this.validateInputs()) { // If inputs are invalid, set focus to the first one and add listeners on them // to detect further changes - const invalidInput = mainWindow.document.getElementsByClassName('invalid-input'); + const invalidInput = this.window.document.getElementsByClassName('invalid-input'); if (invalidInput.length) { (invalidInput[0]).focus(); } @@ -986,6 +145,7 @@ export class IssueReporter extends Disposable { if (this.issueReporterModel.fileOnExtension()) { this.addEventListener('extension-selector', 'change', _ => { this.validateInput('extension-selector'); + this.validateInput('description'); }); } @@ -1020,7 +180,7 @@ export class IssueReporter extends Disposable { console.error('Writing to clipboard failed'); return false; } - } else if (this.configuration.data.githubAccessToken && gitHubDetails) { + } else if (this.data.githubAccessToken && gitHubDetails) { return this.submitToGitHub(issueTitle, issueBody, gitHubDetails); } @@ -1028,8 +188,8 @@ export class IssueReporter extends Disposable { return true; } - private async writeToClipboard(baseUrl: string, issueBody: string): Promise { - const shouldWrite = await this.issueMainService.$showClipboardDialog(); + public override async writeToClipboard(baseUrl: string, issueBody: string): Promise { + const shouldWrite = await this.issueFormService.showClipboardDialog(); if (!shouldWrite) { throw new CancellationError(); } @@ -1039,60 +199,8 @@ export class IssueReporter extends Disposable { return baseUrl + `&body=${encodeURIComponent(localize('pasteData', "We have written the needed data into your clipboard because it was too large to send. Please paste."))}`; } - private getIssueUrl(): string { - return this.issueReporterModel.fileOnExtension() - ? this.getExtensionGitHubUrl() - : this.issueReporterModel.getData().fileOnMarketplace - ? this.configuration.product.reportMarketplaceIssueUrl! - : this.configuration.product.reportIssueUrl!; - } - - private parseGitHubUrl(url: string): undefined | { repositoryName: string; owner: string } { - // Assumes a GitHub url to a particular repo, https://github.com/repositoryName/owner. - // Repository name and owner cannot contain '/' - const match = /^https?:\/\/github\.com\/([^\/]*)\/([^\/]*).*/.exec(url); - if (match && match.length) { - return { - owner: match[1], - repositoryName: match[2] - }; - } else { - console.error('No GitHub issues match'); - } - - return undefined; - } - - private getExtensionGitHubUrl(): string { - let repositoryUrl = ''; - const bugsUrl = this.getExtensionBugsUrl(); - const extensionUrl = this.getExtensionRepositoryUrl(); - // If given, try to match the extension's bug url - if (bugsUrl && bugsUrl.match(/^https?:\/\/github\.com\/([^\/]*)\/([^\/]*)\/?(\/issues)?$/)) { - // matches exactly: https://github.com/owner/repo/issues - repositoryUrl = normalizeGitHubUrl(bugsUrl); - } else if (extensionUrl && extensionUrl.match(/^https?:\/\/github\.com\/([^\/]*)\/([^\/]*)$/)) { - // matches exactly: https://github.com/owner/repo - repositoryUrl = normalizeGitHubUrl(extensionUrl); - } else { - this.nonGitHubIssueUrl = true; - repositoryUrl = bugsUrl || extensionUrl || ''; - } - - return repositoryUrl; - } - - private getIssueUrlWithTitle(issueTitle: string, repositoryUrl: string): string { - if (this.issueReporterModel.fileOnExtension()) { - repositoryUrl = repositoryUrl + '/issues/new'; - } - - const queryStringPrefix = repositoryUrl.indexOf('?') === -1 ? '?' : '&'; - return `${repositoryUrl}${queryStringPrefix}title=${encodeURIComponent(issueTitle)}`; - } - private updateSystemInfo(state: IssueReporterModelData) { - const target = mainWindow.document.querySelector('.block-system .block-info'); + const target = this.window.document.querySelector('.block-system .block-info'); if (target) { const systemInfo = state.systemInfo!; @@ -1171,270 +279,6 @@ export class IssueReporter extends Disposable { } } - private updateExtensionSelector(extensions: OldIssueReporterExtensionData[]): void { - interface IOption { - name: string; - id: string; - } - - const extensionOptions: IOption[] = extensions.map(extension => { - return { - name: extension.displayName || extension.name || '', - id: extension.id - }; - }); - - // Sort extensions by name - extensionOptions.sort((a, b) => { - const aName = a.name.toLowerCase(); - const bName = b.name.toLowerCase(); - if (aName > bName) { - return 1; - } - - if (aName < bName) { - return -1; - } - - return 0; - }); - - const makeOption = (extension: IOption, selectedExtension?: OldIssueReporterExtensionData): HTMLOptionElement => { - const selected = selectedExtension && extension.id === selectedExtension.id; - return $('option', { - 'value': extension.id, - 'selected': selected || '' - }, extension.name); - }; - - const extensionsSelector = this.getElementById('extension-selector'); - if (extensionsSelector) { - const { selectedExtension } = this.issueReporterModel.getData(); - reset(extensionsSelector, this.makeOption('', localize('selectExtension', "Select extension"), true), ...extensionOptions.map(extension => makeOption(extension, selectedExtension))); - - if (!selectedExtension) { - extensionsSelector.selectedIndex = 0; - } - - this.addEventListener('extension-selector', 'change', async (e: Event) => { - this.clearExtensionData(); - const selectedExtensionId = (e.target).value; - this.selectedExtension = selectedExtensionId; - const extensions = this.issueReporterModel.getData().allExtensions; - const matches = extensions.filter(extension => extension.id === selectedExtensionId); - if (matches.length) { - this.issueReporterModel.update({ selectedExtension: matches[0] }); - const selectedExtension = this.issueReporterModel.getData().selectedExtension; - if (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.configuration.data = openReporterData; - } else if (this.selectedExtension !== selectedExtensionId) { - } - } - else { - if (!this.loadingExtensionData) { - iconElement.classList.remove(...ThemeIcon.asClassNameArray(Codicon.loading), 'codicon-modifier-spin'); - } - this.removeLoading(iconElement); - // if not using command, should have no configuration data in fields we care about and check later. - this.clearExtensionData(); - - // case when previous extension was opened from normal openIssueReporter command - 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(); - this.clearExtensionData(); - this.validateSelectedExtension(); - this.updateExtensionStatus(matches[0]); - } - } - }); - } - - this.addEventListener('problem-source', 'change', (_) => { - this.validateSelectedExtension(); - }); - } - - private clearExtensionData(): void { - this.nonGitHubIssueUrl = false; - this.issueReporterModel.update({ extensionData: undefined }); - this.configuration.data.issueBody = undefined; - this.configuration.data.data = undefined; - this.configuration.data.uri = undefined; - } - - private async updateExtensionStatus(extension: OldIssueReporterExtensionData) { - this.issueReporterModel.update({ selectedExtension: extension }); - - // uses this.configuuration.data to ensure that data is coming from `openReporter` command. - const template = this.configuration.data.issueBody; - if (template) { - const descriptionTextArea = this.getElementById('description')!; - const descriptionText = (descriptionTextArea as HTMLTextAreaElement).value; - if (descriptionText === '' || !descriptionText.includes(template.toString())) { - const fullTextArea = descriptionText + (descriptionText === '' ? '' : '\n') + template.toString(); - (descriptionTextArea as HTMLTextAreaElement).value = fullTextArea; - this.issueReporterModel.update({ issueDescription: fullTextArea }); - } - } - - const data = this.configuration.data.data; - if (data) { - this.issueReporterModel.update({ extensionData: data }); - extension.data = data; - const extensionDataBlock = mainWindow.document.querySelector('.block-extension-data')!; - show(extensionDataBlock); - this.renderBlocks(); - } - - const uri = this.configuration.data.uri; - if (uri) { - extension.uri = uri; - this.updateIssueReporterUri(extension); - } - - this.validateSelectedExtension(); - const title = (this.getElementById('issue-title')).value; - this.searchExtensionIssues(title); - - this.updatePreviewButtonState(); - this.renderBlocks(); - } - - private validateSelectedExtension(): void { - const extensionValidationMessage = this.getElementById('extension-selection-validation-error')!; - const extensionValidationNoUrlsMessage = this.getElementById('extension-selection-validation-error-no-url')!; - hide(extensionValidationMessage); - hide(extensionValidationNoUrlsMessage); - - const extension = this.issueReporterModel.getData().selectedExtension; - if (!extension) { - this.previewButton.enabled = true; - return; - } - - if (this.loadingExtensionData) { - return; - } - - const hasValidGitHubUrl = this.getExtensionGitHubUrl(); - if (hasValidGitHubUrl) { - this.previewButton.enabled = true; - } else { - this.setExtensionValidationMessage(); - this.previewButton.enabled = false; - } - } - - private setLoading(element: HTMLElement) { - // Show loading - this.openReporter = true; - this.loadingExtensionData = true; - this.updatePreviewButtonState(); - - const extensionDataCaption = this.getElementById('extension-id')!; - hide(extensionDataCaption); - - const extensionDataCaption2 = Array.from(mainWindow.document.querySelectorAll('.ext-parens')); - extensionDataCaption2.forEach(extensionDataCaption2 => hide(extensionDataCaption2)); - - const showLoading = this.getElementById('ext-loading')!; - show(showLoading); - while (showLoading.firstChild) { - showLoading.firstChild.remove(); - } - showLoading.append(element); - - this.renderBlocks(); - } - - private removeLoading(element: HTMLElement, fromReporter: boolean = false) { - this.openReporter = fromReporter; - this.loadingExtensionData = false; - this.updatePreviewButtonState(); - - const extensionDataCaption = this.getElementById('extension-id')!; - show(extensionDataCaption); - - const extensionDataCaption2 = Array.from(mainWindow.document.querySelectorAll('.ext-parens')); - extensionDataCaption2.forEach(extensionDataCaption2 => show(extensionDataCaption2)); - - const hideLoading = this.getElementById('ext-loading')!; - hide(hideLoading); - if (hideLoading.firstChild) { - element.remove(); - } - this.renderBlocks(); - } - - private setExtensionValidationMessage(): void { - const extensionValidationMessage = this.getElementById('extension-selection-validation-error')!; - const extensionValidationNoUrlsMessage = this.getElementById('extension-selection-validation-error-no-url')!; - const bugsUrl = this.getExtensionBugsUrl(); - if (bugsUrl) { - show(extensionValidationMessage); - const link = this.getElementById('extensionBugsLink')!; - link.textContent = bugsUrl; - return; - } - - const extensionUrl = this.getExtensionRepositoryUrl(); - if (extensionUrl) { - show(extensionValidationMessage); - const link = this.getElementById('extensionBugsLink'); - link!.textContent = extensionUrl; - return; - } - - show(extensionValidationNoUrlsMessage); - } - - private updateProcessInfo(state: IssueReporterModelData) { - const target = mainWindow.document.querySelector('.block-process .block-info') as HTMLElement; - if (target) { - reset(target, $('code', undefined, state.processInfo ?? '')); - } - } - - private updateWorkspaceInfo(state: IssueReporterModelData) { - mainWindow.document.querySelector('.block-workspace .block-info code')!.textContent = '\n' + state.workspaceInfo; - } - - private updateExtensionTable(extensions: OldIssueReporterExtensionData[], numThemeExtensions: number): void { - const target = mainWindow.document.querySelector('.block-extensions .block-info'); - if (target) { - if (this.configuration.disableExtensions) { - reset(target, localize('disabledExtensions', "Extensions are disabled")); - return; - } - - const themeExclusionStr = numThemeExtensions ? `\n(${numThemeExtensions} theme extensions excluded)` : ''; - extensions = extensions || []; - - if (!extensions.length) { - target.innerText = 'Extensions: none' + themeExclusionStr; - return; - } - - reset(target, this.getExtensionTableHtml(extensions), document.createTextNode(themeExclusionStr)); - } - } - private updateRestrictedMode(restrictedMode: boolean) { this.issueReporterModel.update({ restrictedMode }); } @@ -1445,56 +289,9 @@ export class IssueReporter extends Disposable { private updateExperimentsInfo(experimentInfo: string | undefined) { this.issueReporterModel.update({ experimentInfo }); - const target = mainWindow.document.querySelector('.block-experiments .block-info'); + const target = this.window.document.querySelector('.block-experiments .block-info'); if (target) { target.textContent = experimentInfo ? experimentInfo : localize('noCurrentExperiments', "No current experiments."); } } - - private getExtensionTableHtml(extensions: OldIssueReporterExtensionData[]): HTMLTableElement { - return $('table', undefined, - $('tr', undefined, - $('th', undefined, 'Extension'), - $('th', undefined, 'Author (truncated)' as string), - $('th', undefined, 'Version') - ), - ...extensions.map(extension => $('tr', undefined, - $('td', undefined, extension.name), - $('td', undefined, extension.publisher?.substr(0, 3) ?? 'N/A'), - $('td', undefined, extension.version) - )) - ); - } - - private openLink(event: MouseEvent): void { - event.preventDefault(); - event.stopPropagation(); - // Exclude right click - if (event.which < 3) { - windowOpenNoOpener((event.target).href); - } - } - - private getElementById(elementId: string): T | undefined { - const element = mainWindow.document.getElementById(elementId) as T | undefined; - if (element) { - return element; - } else { - return undefined; - } - } - - private addEventListener(elementId: string, eventType: string, handler: (event: Event) => void): void { - const element = this.getElementById(elementId); - element?.addEventListener(eventType, handler); - } -} - -// helper functions - -export function hide(el: Element | undefined | null) { - el?.classList.add('hidden'); -} -export function show(el: Element | undefined | null) { - el?.classList.remove('hidden'); } diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService2.ts b/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService2.ts deleted file mode 100644 index 305ee9a7bc9..00000000000 --- a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService2.ts +++ /dev/null @@ -1,297 +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 { $, reset } from '../../../../base/browser/dom.js'; -import { CancellationError } from '../../../../base/common/errors.js'; -import { IProductConfiguration } from '../../../../base/common/product.js'; -import { URI } from '../../../../base/common/uri.js'; -import { localize } from '../../../../nls.js'; -import { isRemoteDiagnosticError } from '../../../../platform/diagnostics/common/diagnostics.js'; -import { IProcessMainService } from '../../../../platform/issue/common/issue.js'; -import { INativeHostService } from '../../../../platform/native/common/native.js'; -import { IThemeService } from '../../../../platform/theme/common/themeService.js'; -import { applyZoom } from '../../../../platform/window/electron-sandbox/window.js'; -import { BaseIssueReporterService } from '../browser/baseIssueReporterService.js'; -import { IssueReporterData as IssueReporterModelData } from '../browser/issueReporterModel.js'; -import { IIssueFormService, IssueReporterData, IssueType } from '../common/issue.js'; - -// 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 -const MAX_URL_LENGTH = 7500; - - -export class IssueReporter2 extends BaseIssueReporterService { - private readonly processMainService: IProcessMainService; - constructor( - disableExtensions: boolean, - data: IssueReporterData, - os: { - type: string; - arch: string; - release: string; - }, - product: IProductConfiguration, - window: Window, - @INativeHostService private readonly nativeHostService: INativeHostService, - @IIssueFormService issueFormService: IIssueFormService, - @IProcessMainService processMainService: IProcessMainService, - @IThemeService themeService: IThemeService - ) { - super(disableExtensions, data, os, product, window, false, issueFormService, themeService); - this.processMainService = processMainService; - this.processMainService.$getSystemInfo().then(info => { - this.issueReporterModel.update({ systemInfo: info }); - this.receivedSystemInfo = true; - - this.updateSystemInfo(this.issueReporterModel.getData()); - this.updatePreviewButtonState(); - }); - if (this.data.issueType === IssueType.PerformanceIssue) { - this.processMainService.$getPerformanceInfo().then(info => { - this.updatePerformanceInfo(info as Partial); - }); - } - - this.setEventHandlers(); - applyZoom(this.data.zoomLevel, this.window); - this.updateExperimentsInfo(this.data.experiments); - this.updateRestrictedMode(this.data.restrictedMode); - this.updateUnsupportedMode(this.data.isUnsupported); - } - - public override setEventHandlers(): void { - super.setEventHandlers(); - - this.addEventListener('issue-type', 'change', (event: Event) => { - const issueType = parseInt((event.target).value); - this.issueReporterModel.update({ issueType: issueType }); - if (issueType === IssueType.PerformanceIssue && !this.receivedPerformanceInfo) { - this.processMainService.$getPerformanceInfo().then(info => { - this.updatePerformanceInfo(info as Partial); - }); - } - - // Resets placeholder - const descriptionTextArea = this.getElementById('issue-title'); - if (descriptionTextArea) { - descriptionTextArea.placeholder = localize('undefinedPlaceholder', "Please enter a title"); - } - - this.updatePreviewButtonState(); - this.setSourceOptions(); - this.render(); - }); - } - - public override async submitToGitHub(issueTitle: string, issueBody: string, gitHubDetails: { owner: string; repositoryName: string }): Promise { - const url = `https://api.github.com/repos/${gitHubDetails.owner}/${gitHubDetails.repositoryName}/issues`; - const init = { - method: 'POST', - body: JSON.stringify({ - title: issueTitle, - body: issueBody - }), - headers: new Headers({ - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${this.data.githubAccessToken}` - }) - }; - - const response = await fetch(url, init); - if (!response.ok) { - console.error('Invalid GitHub URL provided.'); - return false; - } - const result = await response.json(); - await this.nativeHostService.openExternal(result.html_url); - this.close(); - return true; - } - - public override async createIssue(): Promise { - const selectedExtension = this.issueReporterModel.getData().selectedExtension; - const hasUri = this.nonGitHubIssueUrl; - // Short circuit if the extension provides a custom issue handler - if (hasUri) { - const url = this.getExtensionBugsUrl(); - if (url) { - this.hasBeenSubmitted = true; - await this.nativeHostService.openExternal(url); - return true; - } - } - - if (!this.validateInputs()) { - // If inputs are invalid, set focus to the first one and add listeners on them - // to detect further changes - const invalidInput = this.window.document.getElementsByClassName('invalid-input'); - if (invalidInput.length) { - (invalidInput[0]).focus(); - } - - this.addEventListener('issue-title', 'input', _ => { - this.validateInput('issue-title'); - }); - - this.addEventListener('description', 'input', _ => { - this.validateInput('description'); - }); - - this.addEventListener('issue-source', 'change', _ => { - this.validateInput('issue-source'); - }); - - if (this.issueReporterModel.fileOnExtension()) { - this.addEventListener('extension-selector', 'change', _ => { - this.validateInput('extension-selector'); - this.validateInput('description'); - }); - } - - return false; - } - - this.hasBeenSubmitted = true; - - const issueTitle = (this.getElementById('issue-title')).value; - const issueBody = this.issueReporterModel.serialize(); - - let issueUrl = this.getIssueUrl(); - if (!issueUrl) { - console.error('No issue url found'); - return false; - } - - if (selectedExtension?.uri) { - const uri = URI.revive(selectedExtension.uri); - issueUrl = uri.toString(); - } - - const gitHubDetails = this.parseGitHubUrl(issueUrl); - - const baseUrl = this.getIssueUrlWithTitle((this.getElementById('issue-title')).value, issueUrl); - let url = baseUrl + `&body=${encodeURIComponent(issueBody)}`; - - if (url.length > MAX_URL_LENGTH) { - try { - url = await this.writeToClipboard(baseUrl, issueBody); - } catch (_) { - console.error('Writing to clipboard failed'); - return false; - } - } else if (this.data.githubAccessToken && gitHubDetails) { - return this.submitToGitHub(issueTitle, issueBody, gitHubDetails); - } - - await this.nativeHostService.openExternal(url); - return true; - } - - public override async writeToClipboard(baseUrl: string, issueBody: string): Promise { - const shouldWrite = await this.issueFormService.showClipboardDialog(); - if (!shouldWrite) { - throw new CancellationError(); - } - - await this.nativeHostService.writeClipboardText(issueBody); - - return baseUrl + `&body=${encodeURIComponent(localize('pasteData', "We have written the needed data into your clipboard because it was too large to send. Please paste."))}`; - } - - private updateSystemInfo(state: IssueReporterModelData) { - const target = this.window.document.querySelector('.block-system .block-info'); - - if (target) { - const systemInfo = state.systemInfo!; - const renderedDataTable = $('table', undefined, - $('tr', undefined, - $('td', undefined, 'CPUs'), - $('td', undefined, systemInfo.cpus || '') - ), - $('tr', undefined, - $('td', undefined, 'GPU Status' as string), - $('td', undefined, Object.keys(systemInfo.gpuStatus).map(key => `${key}: ${systemInfo.gpuStatus[key]}`).join('\n')) - ), - $('tr', undefined, - $('td', undefined, 'Load (avg)' as string), - $('td', undefined, systemInfo.load || '') - ), - $('tr', undefined, - $('td', undefined, 'Memory (System)' as string), - $('td', undefined, systemInfo.memory) - ), - $('tr', undefined, - $('td', undefined, 'Process Argv' as string), - $('td', undefined, systemInfo.processArgs) - ), - $('tr', undefined, - $('td', undefined, 'Screen Reader' as string), - $('td', undefined, systemInfo.screenReader) - ), - $('tr', undefined, - $('td', undefined, 'VM'), - $('td', undefined, systemInfo.vmHint) - ) - ); - reset(target, renderedDataTable); - - systemInfo.remoteData.forEach(remote => { - target.appendChild($('hr')); - if (isRemoteDiagnosticError(remote)) { - const remoteDataTable = $('table', undefined, - $('tr', undefined, - $('td', undefined, 'Remote'), - $('td', undefined, remote.hostName) - ), - $('tr', undefined, - $('td', undefined, ''), - $('td', undefined, remote.errorMessage) - ) - ); - target.appendChild(remoteDataTable); - } else { - const remoteDataTable = $('table', undefined, - $('tr', undefined, - $('td', undefined, 'Remote'), - $('td', undefined, remote.latency ? `${remote.hostName} (latency: ${remote.latency.current.toFixed(2)}ms last, ${remote.latency.average.toFixed(2)}ms average)` : remote.hostName) - ), - $('tr', undefined, - $('td', undefined, 'OS'), - $('td', undefined, remote.machineInfo.os) - ), - $('tr', undefined, - $('td', undefined, 'CPUs'), - $('td', undefined, remote.machineInfo.cpus || '') - ), - $('tr', undefined, - $('td', undefined, 'Memory (System)' as string), - $('td', undefined, remote.machineInfo.memory) - ), - $('tr', undefined, - $('td', undefined, 'VM'), - $('td', undefined, remote.machineInfo.vmHint) - ) - ); - target.appendChild(remoteDataTable); - } - }); - } - } - - private updateRestrictedMode(restrictedMode: boolean) { - this.issueReporterModel.update({ restrictedMode }); - } - - private updateUnsupportedMode(isUnsupported: boolean) { - this.issueReporterModel.update({ isUnsupported }); - } - - private updateExperimentsInfo(experimentInfo: string | undefined) { - this.issueReporterModel.update({ experimentInfo }); - const target = this.window.document.querySelector('.block-experiments .block-info'); - if (target) { - target.textContent = experimentInfo ? experimentInfo : localize('noCurrentExperiments', "No current experiments."); - } - } -} diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/issueService.ts b/src/vs/workbench/contrib/issue/electron-sandbox/issueService.ts index 2ee3df7cf70..7587d24af5b 100644 --- a/src/vs/workbench/contrib/issue/electron-sandbox/issueService.ts +++ b/src/vs/workbench/contrib/issue/electron-sandbox/issueService.ts @@ -5,15 +5,10 @@ import { getZoomLevel } from '../../../../base/browser/browser.js'; import { mainWindow } from '../../../../base/browser/window.js'; -import { ipcRenderer } from '../../../../base/parts/sandbox/electron-sandbox/globals.js'; -import { IMenuService, MenuId } from '../../../../platform/actions/common/actions.js'; -import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js'; -import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js'; import { IExtensionManagementService } from '../../../../platform/extensionManagement/common/extensionManagement.js'; -import { ExtensionIdentifier, ExtensionIdentifierSet, ExtensionType } from '../../../../platform/extensions/common/extensions.js'; +import { ExtensionType } from '../../../../platform/extensions/common/extensions.js'; import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js'; -import { IIssueMainService, OldIssueReporterData, OldIssueReporterExtensionData, OldIssueReporterStyles } from '../../../../platform/issue/common/issue.js'; -import { buttonBackground, buttonForeground, buttonHoverBackground, foreground, inputActiveOptionBorder, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, textLinkActiveForeground, textLinkForeground } from '../../../../platform/theme/common/colorRegistry.js'; +import { buttonBackground, buttonForeground, buttonHoverBackground, foreground, inputActiveOptionBorder, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, scrollbarSliderActiveBackground, scrollbarSliderHoverBackground, textLinkActiveForeground, textLinkForeground } from '../../../../platform/theme/common/colorRegistry.js'; import { IColorTheme, IThemeService } from '../../../../platform/theme/common/themeService.js'; import { IWorkspaceTrustManagementService } from '../../../../platform/workspace/common/workspaceTrust.js'; import { SIDE_BAR_BACKGROUND } from '../../../common/theme.js'; @@ -25,10 +20,8 @@ import { IIntegrityService } from '../../../services/integrity/common/integrity. export class NativeIssueService implements IWorkbenchIssueService { declare readonly _serviceBrand: undefined; - private extensionIdentifierSet: ExtensionIdentifierSet = new ExtensionIdentifierSet(); constructor( - @IIssueMainService private readonly issueMainService: IIssueMainService, @IIssueFormService private readonly issueFormService: IIssueFormService, @IThemeService private readonly themeService: IThemeService, @IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService, @@ -37,39 +30,10 @@ export class NativeIssueService implements IWorkbenchIssueService { @IWorkbenchAssignmentService private readonly experimentService: IWorkbenchAssignmentService, @IAuthenticationService private readonly authenticationService: IAuthenticationService, @IIntegrityService private readonly integrityService: IIntegrityService, - @IMenuService private readonly menuService: IMenuService, - @IContextKeyService private readonly contextKeyService: IContextKeyService, - @IConfigurationService private readonly configurationService: IConfigurationService - ) { - ipcRenderer.on('vscode:triggerReporterMenu', async (event, arg) => { - const extensionId = arg.extensionId; - - // gets menu from contributed - const actions = this.menuService.getMenuActions(MenuId.IssueReporter, this.contextKeyService, { renderShortTitle: true }).flatMap(entry => entry[1]); - - // render menu and dispose - actions.forEach(async action => { - try { - if (action.item && 'source' in action.item && action.item.source?.id === extensionId) { - this.extensionIdentifierSet.add(extensionId); - await action.run(); - } - } catch (error) { - console.error(error); - } - }); - - if (!this.extensionIdentifierSet.has(extensionId)) { - // send undefined to indicate no action was taken - ipcRenderer.send(`vscode:triggerReporterMenuResponse:${extensionId}`, undefined); - } - }); - } + ) { } async openReporter(dataOverrides: Partial = {}): Promise { const extensionData: IssueReporterExtensionData[] = []; - const oldExtensionData: OldIssueReporterExtensionData[] = []; - const oldDataOverrides = dataOverrides as Partial; try { const extensions = await this.extensionManagementService.getInstalled(); const enabledExtensions = extensions.filter(extension => this.extensionEnablementService.isEnabled(extension) || (dataOverrides.extensionId && extension.identifier.id === dataOverrides.extensionId)); @@ -93,26 +57,6 @@ export class NativeIssueService implements IWorkbenchIssueService { extensionData: 'Extensions data loading', }; })); - oldExtensionData.push(...enabledExtensions.map((extension): OldIssueReporterExtensionData => { - 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: dataOverrides.data, - uri: dataOverrides.uri, - isTheme, - isBuiltin, - extensionData: 'Extensions data loading', - }; - })); } catch (e) { extensionData.push({ name: 'Workbench Issue Service', @@ -126,18 +70,6 @@ export class NativeIssueService implements IWorkbenchIssueService { isTheme: false, isBuiltin: true }); - oldExtensionData.push({ - name: 'Workbench Issue Service', - publisher: 'Unknown', - version: '0.0.0', - repositoryUrl: undefined, - bugsUrl: undefined, - extensionData: 'Extensions data loading', - displayName: `Extensions not loaded: ${e}`, - id: 'workbench.issue', - isTheme: false, - isBuiltin: true - }); } const experiments = await this.experimentService.getCurrentExperiments(); @@ -169,34 +101,7 @@ export class NativeIssueService implements IWorkbenchIssueService { githubAccessToken }, dataOverrides); - const oldIssueReporterData: OldIssueReporterData = Object.assign({ - styles: oldGetIssueReporterStyles(theme), - zoomLevel: getZoomLevel(mainWindow), - enabledExtensions: oldExtensionData, - experiments: experiments?.join('\n'), - restrictedMode: !this.workspaceTrustManagementService.isWorkspaceTrusted(), - isUnsupported, - githubAccessToken - }, oldDataOverrides); - - if (issueReporterData.extensionId) { - const extensionExists = extensionData.some(extension => ExtensionIdentifier.equals(extension.id, issueReporterData.extensionId)); - if (!extensionExists) { - console.error(`Extension with ID ${issueReporterData.extensionId} does not exist.`); - } - } - - if (issueReporterData.extensionId && this.extensionIdentifierSet.has(issueReporterData.extensionId)) { - ipcRenderer.send(`vscode:triggerReporterMenuResponse:${issueReporterData.extensionId}`, issueReporterData); - this.extensionIdentifierSet.delete(new ExtensionIdentifier(issueReporterData.extensionId)); - } - - - if (this.configurationService.getValue('issueReporter.experimental.auxWindow')) { - return this.issueFormService.openReporter(issueReporterData); - } - - return this.issueMainService.openReporter(oldIssueReporterData); + return this.issueFormService.openReporter(issueReporterData); } } @@ -223,28 +128,6 @@ export function getIssueReporterStyles(theme: IColorTheme): IssueReporterStyles }; } -export function oldGetIssueReporterStyles(theme: IColorTheme): OldIssueReporterStyles { - 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; diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/media/issueReporter.css b/src/vs/workbench/contrib/issue/electron-sandbox/media/issueReporter.css index 6f8e7abe204..c88a95a95e0 100644 --- a/src/vs/workbench/contrib/issue/electron-sandbox/media/issueReporter.css +++ b/src/vs/workbench/contrib/issue/electron-sandbox/media/issueReporter.css @@ -3,56 +3,54 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -/* -* TODO: @justschen - remove this file once the new issue reporter is enabled by default. -* Split between this and a `newIssueReporter` because of specificy from new issue reporter monaco-workbench stylesheets. -*/ - /** * Table */ -table { +.issue-reporter-body table { width: 100%; max-width: 100%; background-color: transparent; border-collapse: collapse; } -th { + +.issue-reporter-body th { vertical-align: bottom; border-bottom: 1px solid; padding: 5px; text-align: inherit; } -td { + +.issue-reporter-body td { padding: 5px; vertical-align: top; } -tr td:first-child { +.issue-reporter-body tr td:first-child { width: 30%; } -label { +.issue-reporter-body label { user-select: none; } -.block-settingsSearchResults-details { +.issue-reporter-body .block-settingsSearchResults-details { padding-bottom: .5rem; } -.block-settingsSearchResults-details > div { +.issue-reporter-body .block-settingsSearchResults-details > div { padding: .5rem .75rem; } -.section { +.issue-reporter-body .section { margin-bottom: .5em; } /** * Forms */ -input[type="text"], textarea { +.issue-reporter-body input[type="text"], +.issue-reporter-body textarea { display: block; width: 100%; padding: .375rem .75rem; @@ -63,7 +61,7 @@ input[type="text"], textarea { border: 1px solid #ced4da; } -textarea { +.issue-reporter-body textarea { overflow: auto; resize: vertical; } @@ -72,7 +70,7 @@ textarea { * Button */ -.monaco-text-button { +.issue-reporter-body .monaco-text-button { display: block; width: auto; padding: 4px 10px; @@ -81,7 +79,7 @@ textarea { font-size: 13px; } -select { +.issue-reporter-body select { height: calc(2.25rem + 2px); display: inline-block; padding: 3px 3px; @@ -92,60 +90,104 @@ select { border: none; } -* { +.issue-reporter-body * { box-sizing: border-box; } -textarea, input, select { +.issue-reporter-body textarea, +.issue-reporter-body input, +.issue-reporter-body select { font-family: inherit; } -html { +.issue-reporter-body html { color: #CCCCCC; height: 100%; } -.extension-caption .codicon-modifier-spin { +.issue-reporter-body .extension-caption .codicon-modifier-spin { padding-bottom: 3px; margin-left: 2px; } /* Font Families (with CJK support) */ -.mac { font-family: -apple-system, BlinkMacSystemFont, sans-serif; } -.mac:lang(zh-Hans) { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; } -.mac:lang(zh-Hant) { font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; } -.mac:lang(ja) { font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; } -.mac:lang(ko) { font-family: -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Nanum Gothic", "AppleGothic", sans-serif; } - -.windows { font-family: "Segoe WPC", "Segoe UI", sans-serif; } -.windows:lang(zh-Hans) { font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; } -.windows:lang(zh-Hant) { font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; } -.windows:lang(ja) { font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; } -.windows:lang(ko) { font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; } - -/* Linux: add `system-ui` as first font and not `Ubuntu` to allow other distribution pick their standard OS font */ -.linux { font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; } -.linux:lang(zh-Hans) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; } -.linux:lang(zh-Hant) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif; } -.linux:lang(ja) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; } -.linux: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; } - -body { - margin: 0; - overflow-y: scroll; - height: 100%; +.issue-reporter-body .mac { + font-family: -apple-system, BlinkMacSystemFont, sans-serif; } -.hidden { +.issue-reporter-body .mac:lang(zh-Hans) { + font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; +} + +.issue-reporter-body .mac:lang(zh-Hant) { + font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; +} + +.issue-reporter-body .mac:lang(ja) { + font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; +} + +.issue-reporter-body .mac:lang(ko) { + font-family: -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Nanum Gothic", "AppleGothic", sans-serif; +} + +.issue-reporter-body .windows { + font-family: "Segoe WPC", "Segoe UI", sans-serif; +} + +.issue-reporter-body .windows:lang(zh-Hans) { + font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; +} + +.issue-reporter-body .windows:lang(zh-Hant) { + font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; +} + +.issue-reporter-body .windows:lang(ja) { + font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; +} + +.issue-reporter-body .windows:lang(ko) { + font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; +} + +/* Linux: add `system-ui` as first font and not `Ubuntu` to allow other distribution pick their standard OS font */ +.issue-reporter-body .linux { + font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; +} + +.issue-reporter-body .linux: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-body .linux: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-body .linux:lang(ja) { + font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; +} + +.issue-reporter-body .linux: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; +} + +body.issue-reporter-body { + margin: 0 !important; + overflow-y: scroll !important; + height: 100% !important; +} + +.issue-reporter-body .hidden { display: none; } -.block { +.issue-reporter-body .block { font-size: 12px; } -.block .block-info { +.issue-reporter-body .block .block-info { width: 100%; font-size: 12px; overflow: auto; @@ -154,7 +196,7 @@ body { padding: 10px; } -#issue-reporter { +.issue-reporter-body #issue-reporter { max-width: 85vw; margin-left: auto; margin-right: auto; @@ -166,65 +208,67 @@ body { overflow: visible; } -.description-section { +.issue-reporter-body .description-section { flex-grow: 1; display: flex; flex-direction: column; flex-shrink: 0; } -textarea { +.issue-reporter-body textarea { flex-grow: 1; min-height: 150px; } -.block-info-text { +.issue-reporter-body .block-info-text { display: flex; flex-grow: 1; } -#github-submit-btn { +.issue-reporter-body #github-submit-btn { flex-shrink: 0; margin-left: auto; margin-top: 10px; margin-bottom: 10px; } -.two-col { +.issue-reporter-body .two-col { display: inline-block; width: 49%; } -#vscode-version { +.issue-reporter-body #vscode-version { width: 90%; } -.input-group { +.issue-reporter-body .input-group { margin-bottom: 1em; } -#extension-selection { +.issue-reporter-body #extension-selection { margin-top: 1em; } -select, input, textarea { +.issue-reporter-body .issue-reporter select, +.issue-reporter-body .issue-reporter input, +.issue-reporter-body .issue-reporter textarea { border: 1px solid transparent; margin-top: 10px; } -#issue-reporter .validation-error { +.issue-reporter-body #issue-reporter .validation-error { font-size: 12px; padding: 10px; border-top: 0px !important; } -#issue-reporter .system-info { +.issue-reporter-body #issue-reporter .system-info { margin-bottom: 10px; } -input[type="checkbox"] { +.issue-reporter-body input[type="checkbox"] { width: auto; display: inline-block; margin-top: 0; @@ -232,136 +276,166 @@ input[type="checkbox"] { cursor: pointer; } -input:disabled { +.issue-reporter-body input:disabled { opacity: 0.6; } -.list-title { +.issue-reporter-body .list-title { margin-top: 1em; margin-left: 1em; } -.instructions { +.issue-reporter-body .instructions { font-size: 12px; margin-top: .5em; } -a, .workbenchCommand { +.issue-reporter-body a, +.issue-reporter-body .workbenchCommand { cursor: pointer; border: 1px solid transparent; } -.workbenchCommand:disabled { +.issue-reporter-body .workbenchCommand:disabled { color: #868e96; cursor: default } -.block-extensions .block-info { +.issue-reporter-body .block-extensions .block-info { margin-bottom: 1.5em; } /* Default styles, overwritten if a theme is provided */ -input, select, textarea { +.issue-reporter-body input, +.issue-reporter-body select, +.issue-reporter-body textarea { background-color: #3c3c3c; border: none; color: #cccccc; } -a { +.issue-reporter-body a { color: #CCCCCC; text-decoration: none; } -.section .input-group .validation-error { +.issue-reporter-body .showInfo, +.issue-reporter-body .input-group a { + color: var(--vscode-textLink-foreground); +} + +.issue-reporter-body .section .input-group .validation-error { margin-left: 100px; } -.section .inline-form-control, .section .inline-label { +.issue-reporter-body .section .inline-form-control, +.issue-reporter-body .section .inline-label { display: inline-block; + font-size: initial; } -.section .inline-label { +.issue-reporter-body .section .inline-label { width: 95px; } -.section .inline-form-control, .section .input-group .validation-error { +.issue-reporter-body .issue-reporter .inline-label, +.issue-reporter-body .issue-reporter #issue-description-label { + font-size: initial; + cursor: default; +} + +.issue-reporter-body .monaco-workbench .issue-reporter label { + cursor: default; +} + +.issue-reporter-body .section .inline-form-control, +.issue-reporter-body .section .input-group .validation-error { width: calc(100% - 100px); } -#issue-type { +.issue-reporter-body #issue-type, +.issue-reporter-body #issue-source, +.issue-reporter-body #extension-selector { cursor: pointer; + appearance: auto; + border: none; + border-right: 6px solid transparent; + padding-left: 10px; } -#similar-issues { +.issue-reporter-body #similar-issues { margin-left: 15%; display: block; } -#problem-source-help-text { +.issue-reporter-body #problem-source-help-text { margin-left: calc(15% + 1em); } @media (max-width: 950px) { - .section .inline-label { + .issue-reporter-body .section .inline-label { width: 15%; } - #problem-source-help-text { + .issue-reporter-body #problem-source-help-text { margin-left: calc(15% + 1em); } - .section .inline-form-control, .section .input-group .validation-error { + .issue-reporter-body .section .inline-form-control, + .issue-reporter-body .section .input-group .validation-error { width: calc(85% - 5px); } - .section .input-group .validation-error { + .issue-reporter-body .section .input-group .validation-error { margin-left: calc(15% + 4px); } } @media (max-width: 620px) { - .section .inline-label { + .issue-reporter-body .section .inline-label { display: none !important; } - #problem-source-help-text { + .issue-reporter-body #problem-source-help-text { margin-left: 1em; } - .section .inline-form-control, .section .input-group .validation-error { + .issue-reporter-body .section .inline-form-control, + .issue-reporter-body .section .input-group .validation-error { width: 100%; } - #similar-issues, .section .input-group .validation-error { + .issue-reporter-body #similar-issues, + .issue-reporter-body .section .input-group .validation-error { margin-left: 0; } } -::-webkit-scrollbar { +.issue-reporter-body::-webkit-scrollbar { width: 14px; } -::-webkit-scrollbar-thumb { +.issue-reporter-body::-webkit-scrollbar-thumb { min-height: 20px; } -::-webkit-scrollbar-corner { +.issue-reporter-body::-webkit-scrollbar-corner { display: none; } -.issues-container { +.issue-reporter-body .issues-container { margin-left: 1.5em; margin-top: .5em; max-height: 92px; overflow-y: auto; } -.issues-container > .issue { +.issue-reporter-body .issues-container > .issue { padding: 4px 0; display: flex; } -.issues-container > .issue > .issue-link { +.issue-reporter-body .issues-container > .issue > .issue-link { width: calc(100% - 82px); overflow: hidden; padding-top: 3px; @@ -369,11 +443,11 @@ a { text-overflow: ellipsis; } -.issues-container > .issue > .issue-state .codicon { +.issue-reporter-body .issues-container > .issue > .issue-state .codicon { width: 16px; } -.issues-container > .issue > .issue-state { +.issue-reporter-body .issues-container > .issue > .issue-state { display: flex; width: 77px; padding: 3px 6px; @@ -383,7 +457,7 @@ a { border-radius: .25rem; } -.issues-container > .issue .label { +.issue-reporter-body .issues-container > .issue .label { padding-top: 2px; margin-left: 5px; width: 44px; @@ -391,6 +465,6 @@ a { overflow: hidden; } -.issues-container > .issue .issue-icon{ +.issue-reporter-body .issues-container > .issue .issue-icon { padding-top: 2px; } diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/media/newIssueReporter.css b/src/vs/workbench/contrib/issue/electron-sandbox/media/newIssueReporter.css deleted file mode 100644 index c88a95a95e0..00000000000 --- a/src/vs/workbench/contrib/issue/electron-sandbox/media/newIssueReporter.css +++ /dev/null @@ -1,470 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/** - * Table - */ - -.issue-reporter-body table { - width: 100%; - max-width: 100%; - background-color: transparent; - border-collapse: collapse; -} - -.issue-reporter-body th { - vertical-align: bottom; - border-bottom: 1px solid; - padding: 5px; - text-align: inherit; -} - -.issue-reporter-body td { - padding: 5px; - vertical-align: top; -} - -.issue-reporter-body tr td:first-child { - width: 30%; -} - -.issue-reporter-body label { - user-select: none; -} - -.issue-reporter-body .block-settingsSearchResults-details { - padding-bottom: .5rem; -} - -.issue-reporter-body .block-settingsSearchResults-details > div { - padding: .5rem .75rem; -} - -.issue-reporter-body .section { - margin-bottom: .5em; -} - -/** - * Forms - */ -.issue-reporter-body input[type="text"], -.issue-reporter-body 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-body textarea { - overflow: auto; - resize: vertical; -} - -/** - * Button - */ - -.issue-reporter-body .monaco-text-button { - display: block; - width: auto; - padding: 4px 10px; - align-self: flex-end; - margin-bottom: 1em; - font-size: 13px; -} - -.issue-reporter-body 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-body * { - box-sizing: border-box; -} - -.issue-reporter-body textarea, -.issue-reporter-body input, -.issue-reporter-body select { - font-family: inherit; -} - -.issue-reporter-body html { - color: #CCCCCC; - height: 100%; -} - -.issue-reporter-body .extension-caption .codicon-modifier-spin { - padding-bottom: 3px; - margin-left: 2px; -} - -/* Font Families (with CJK support) */ - -.issue-reporter-body .mac { - font-family: -apple-system, BlinkMacSystemFont, sans-serif; -} - -.issue-reporter-body .mac:lang(zh-Hans) { - font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; -} - -.issue-reporter-body .mac:lang(zh-Hant) { - font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; -} - -.issue-reporter-body .mac:lang(ja) { - font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; -} - -.issue-reporter-body .mac:lang(ko) { - font-family: -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Nanum Gothic", "AppleGothic", sans-serif; -} - -.issue-reporter-body .windows { - font-family: "Segoe WPC", "Segoe UI", sans-serif; -} - -.issue-reporter-body .windows:lang(zh-Hans) { - font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; -} - -.issue-reporter-body .windows:lang(zh-Hant) { - font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; -} - -.issue-reporter-body .windows:lang(ja) { - font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; -} - -.issue-reporter-body .windows:lang(ko) { - font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; -} - -/* Linux: add `system-ui` as first font and not `Ubuntu` to allow other distribution pick their standard OS font */ -.issue-reporter-body .linux { - font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; -} - -.issue-reporter-body .linux: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-body .linux: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-body .linux:lang(ja) { - font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; -} - -.issue-reporter-body .linux: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; -} - -body.issue-reporter-body { - margin: 0 !important; - overflow-y: scroll !important; - height: 100% !important; -} - -.issue-reporter-body .hidden { - display: none; -} - -.issue-reporter-body .block { - font-size: 12px; -} - -.issue-reporter-body .block .block-info { - width: 100%; - font-size: 12px; - overflow: auto; - overflow-wrap: break-word; - margin: 5px; - padding: 10px; -} - -.issue-reporter-body #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-body .description-section { - flex-grow: 1; - display: flex; - flex-direction: column; - flex-shrink: 0; -} - -.issue-reporter-body textarea { - flex-grow: 1; - min-height: 150px; -} - -.issue-reporter-body .block-info-text { - display: flex; - flex-grow: 1; -} - -.issue-reporter-body #github-submit-btn { - flex-shrink: 0; - margin-left: auto; - margin-top: 10px; - margin-bottom: 10px; -} - -.issue-reporter-body .two-col { - display: inline-block; - width: 49%; -} - -.issue-reporter-body #vscode-version { - width: 90%; -} - -.issue-reporter-body .input-group { - margin-bottom: 1em; -} - -.issue-reporter-body #extension-selection { - margin-top: 1em; -} - -.issue-reporter-body .issue-reporter select, -.issue-reporter-body .issue-reporter input, -.issue-reporter-body .issue-reporter textarea { - border: 1px solid transparent; - margin-top: 10px; -} - - -.issue-reporter-body #issue-reporter .validation-error { - font-size: 12px; - padding: 10px; - border-top: 0px !important; -} - -.issue-reporter-body #issue-reporter .system-info { - margin-bottom: 10px; -} - - -.issue-reporter-body input[type="checkbox"] { - width: auto; - display: inline-block; - margin-top: 0; - vertical-align: middle; - cursor: pointer; -} - -.issue-reporter-body input:disabled { - opacity: 0.6; -} - -.issue-reporter-body .list-title { - margin-top: 1em; - margin-left: 1em; -} - -.issue-reporter-body .instructions { - font-size: 12px; - margin-top: .5em; -} - -.issue-reporter-body a, -.issue-reporter-body .workbenchCommand { - cursor: pointer; - border: 1px solid transparent; -} - -.issue-reporter-body .workbenchCommand:disabled { - color: #868e96; - cursor: default -} - -.issue-reporter-body .block-extensions .block-info { - margin-bottom: 1.5em; -} - -/* Default styles, overwritten if a theme is provided */ -.issue-reporter-body input, -.issue-reporter-body select, -.issue-reporter-body textarea { - background-color: #3c3c3c; - border: none; - color: #cccccc; -} - -.issue-reporter-body a { - color: #CCCCCC; - text-decoration: none; -} - -.issue-reporter-body .showInfo, -.issue-reporter-body .input-group a { - color: var(--vscode-textLink-foreground); -} - -.issue-reporter-body .section .input-group .validation-error { - margin-left: 100px; -} - -.issue-reporter-body .section .inline-form-control, -.issue-reporter-body .section .inline-label { - display: inline-block; - font-size: initial; -} - -.issue-reporter-body .section .inline-label { - width: 95px; -} - -.issue-reporter-body .issue-reporter .inline-label, -.issue-reporter-body .issue-reporter #issue-description-label { - font-size: initial; - cursor: default; -} - -.issue-reporter-body .monaco-workbench .issue-reporter label { - cursor: default; -} - -.issue-reporter-body .section .inline-form-control, -.issue-reporter-body .section .input-group .validation-error { - width: calc(100% - 100px); -} - -.issue-reporter-body #issue-type, -.issue-reporter-body #issue-source, -.issue-reporter-body #extension-selector { - cursor: pointer; - appearance: auto; - border: none; - border-right: 6px solid transparent; - padding-left: 10px; -} - -.issue-reporter-body #similar-issues { - margin-left: 15%; - display: block; -} - -.issue-reporter-body #problem-source-help-text { - margin-left: calc(15% + 1em); -} - -@media (max-width: 950px) { - .issue-reporter-body .section .inline-label { - width: 15%; - } - - .issue-reporter-body #problem-source-help-text { - margin-left: calc(15% + 1em); - } - - .issue-reporter-body .section .inline-form-control, - .issue-reporter-body .section .input-group .validation-error { - width: calc(85% - 5px); - } - - .issue-reporter-body .section .input-group .validation-error { - margin-left: calc(15% + 4px); - } -} - -@media (max-width: 620px) { - .issue-reporter-body .section .inline-label { - display: none !important; - } - - .issue-reporter-body #problem-source-help-text { - margin-left: 1em; - } - - .issue-reporter-body .section .inline-form-control, - .issue-reporter-body .section .input-group .validation-error { - width: 100%; - } - - .issue-reporter-body #similar-issues, - .issue-reporter-body .section .input-group .validation-error { - margin-left: 0; - } -} - -.issue-reporter-body::-webkit-scrollbar { - width: 14px; -} - -.issue-reporter-body::-webkit-scrollbar-thumb { - min-height: 20px; -} - -.issue-reporter-body::-webkit-scrollbar-corner { - display: none; -} - -.issue-reporter-body .issues-container { - margin-left: 1.5em; - margin-top: .5em; - max-height: 92px; - overflow-y: auto; -} - -.issue-reporter-body .issues-container > .issue { - padding: 4px 0; - display: flex; -} - -.issue-reporter-body .issues-container > .issue > .issue-link { - width: calc(100% - 82px); - overflow: hidden; - padding-top: 3px; - white-space: nowrap; - text-overflow: ellipsis; -} - -.issue-reporter-body .issues-container > .issue > .issue-state .codicon { - width: 16px; -} - -.issue-reporter-body .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-body .issues-container > .issue .label { - padding-top: 2px; - margin-left: 5px; - width: 44px; - text-overflow: ellipsis; - overflow: hidden; -} - -.issue-reporter-body .issues-container > .issue .issue-icon { - padding-top: 2px; -} diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/nativeIssueFormService.ts b/src/vs/workbench/contrib/issue/electron-sandbox/nativeIssueFormService.ts index 508137162ca..c202234088a 100644 --- a/src/vs/workbench/contrib/issue/electron-sandbox/nativeIssueFormService.ts +++ b/src/vs/workbench/contrib/issue/electron-sandbox/nativeIssueFormService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import './media/newIssueReporter.css'; +import './media/issueReporter.css'; import { IMenuService } from '../../../../platform/actions/common/actions.js'; import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js'; import { IDialogService } from '../../../../platform/dialogs/common/dialogs.js'; @@ -14,7 +14,7 @@ import { INativeHostService } from '../../../../platform/native/common/native.js import product from '../../../../platform/product/common/product.js'; import { IssueFormService } from '../browser/issueFormService.js'; import { IIssueFormService, IssueReporterData } from '../common/issue.js'; -import { IssueReporter2 } from './issueReporterService2.js'; +import { IssueReporter } from './issueReporterService.js'; import { IAuxiliaryWindowService } from '../../../services/auxiliaryWindow/browser/auxiliaryWindowService.js'; import { IHostService } from '../../../services/host/browser/host.js'; @@ -53,7 +53,7 @@ export class NativeIssueFormService extends IssueFormService implements IIssueFo // create issue reporter and instantiate if (this.issueReporterWindow) { - const issueReporter = this.instantiationService.createInstance(IssueReporter2, !!this.environmentService.disableExtensions, data, { type: this.type, arch: this.arch, release: this.release }, product, this.issueReporterWindow); + const issueReporter = this.instantiationService.createInstance(IssueReporter, !!this.environmentService.disableExtensions, data, { type: this.type, arch: this.arch, release: this.release }, product, this.issueReporterWindow); issueReporter.render(); } } diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/process.contribution.ts b/src/vs/workbench/contrib/issue/electron-sandbox/process.contribution.ts index 6c33d9f8133..75826f51d8e 100644 --- a/src/vs/workbench/contrib/issue/electron-sandbox/process.contribution.ts +++ b/src/vs/workbench/contrib/issue/electron-sandbox/process.contribution.ts @@ -13,10 +13,9 @@ import { INativeEnvironmentService } from '../../../../platform/environment/comm import { IDialogService } from '../../../../platform/dialogs/common/dialogs.js'; import { INativeHostService } from '../../../../platform/native/common/native.js'; import { IProgressService, ProgressLocation } from '../../../../platform/progress/common/progress.js'; -import { IProcessMainService } from '../../../../platform/issue/common/issue.js'; +import { IProcessMainService } from '../../../../platform/process/common/process.js'; import './processService.js'; -import './issueMainService.js'; - +import './processMainService.js'; //#region Commands diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/issueMainService.ts b/src/vs/workbench/contrib/issue/electron-sandbox/processMainService.ts similarity index 76% rename from src/vs/workbench/contrib/issue/electron-sandbox/issueMainService.ts rename to src/vs/workbench/contrib/issue/electron-sandbox/processMainService.ts index 32cbb69428d..d2073829039 100644 --- a/src/vs/workbench/contrib/issue/electron-sandbox/issueMainService.ts +++ b/src/vs/workbench/contrib/issue/electron-sandbox/processMainService.ts @@ -4,8 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { registerMainProcessRemoteService } from '../../../../platform/ipc/electron-sandbox/services.js'; -import { IProcessMainService, IIssueMainService } from '../../../../platform/issue/common/issue.js'; +import { IProcessMainService } from '../../../../platform/process/common/process.js'; -registerMainProcessRemoteService(IIssueMainService, 'issue'); registerMainProcessRemoteService(IProcessMainService, 'process'); diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/processService.ts b/src/vs/workbench/contrib/issue/electron-sandbox/processService.ts index c781a4af73c..d5837297bed 100644 --- a/src/vs/workbench/contrib/issue/electron-sandbox/processService.ts +++ b/src/vs/workbench/contrib/issue/electron-sandbox/processService.ts @@ -6,7 +6,7 @@ import { getZoomLevel } from '../../../../base/browser/browser.js'; import { platform } from '../../../../base/common/process.js'; import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js'; -import { IProcessMainService, ProcessExplorerData } from '../../../../platform/issue/common/issue.js'; +import { IProcessMainService, ProcessExplorerData } from '../../../../platform/process/common/process.js'; import { IProductService } from '../../../../platform/product/common/productService.js'; import { activeContrastBorder, editorBackground, editorForeground, listActiveSelectionBackground, listActiveSelectionForeground, listFocusBackground, listFocusForeground, listFocusOutline, listHoverBackground, listHoverForeground, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground } from '../../../../platform/theme/common/colorRegistry.js'; import { IColorTheme, IThemeService } from '../../../../platform/theme/common/themeService.js';