Skip to content

Commit 60d035d

Browse files
authored
issue reporter refactor (web prep) (#212762)
* kinda beeeg refactor * swap the extended issue reporteR * update PR commentsgit add .!
1 parent cdf9453 commit 60d035d

File tree

8 files changed

+1921
-5
lines changed

8 files changed

+1921
-5
lines changed

src/vs/code/browser/issue/issue.ts

Lines changed: 1205 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
import { $, reset, windowOpenNoOpener } from 'vs/base/browser/dom';
6+
import { groupBy } from 'vs/base/common/collections';
7+
import { isMacintosh } from 'vs/base/common/platform';
8+
import { IProductConfiguration } from 'vs/base/common/product';
9+
import { BaseIssueReporterService } from 'vs/code/browser/issue/issue';
10+
import { localize } from 'vs/nls';
11+
import { IIssueMainService, IssueReporterData, IssueReporterExtensionData } from 'vs/platform/issue/common/issue';
12+
13+
// GitHub has let us know that we could up our limit here to 8k. We chose 7500 to play it safe.
14+
// ref https://github.com/microsoft/vscode/issues/159191
15+
16+
export class IssueWebReporter extends BaseIssueReporterService {
17+
constructor(
18+
disableExtensions: boolean,
19+
data: IssueReporterData,
20+
os: {
21+
type: string;
22+
arch: string;
23+
release: string;
24+
},
25+
product: IProductConfiguration,
26+
window: Window,
27+
@IIssueMainService issueMainService: IIssueMainService
28+
) {
29+
super(disableExtensions, data, os, product, window, true, issueMainService);
30+
this.setEventHandlers();
31+
this.handleExtensionData(data.enabledExtensions);
32+
}
33+
34+
private handleExtensionData(extensions: IssueReporterExtensionData[]) {
35+
const installedExtensions = extensions.filter(x => !x.isBuiltin);
36+
const { nonThemes, themes } = groupBy(installedExtensions, ext => {
37+
return ext.isTheme ? 'themes' : 'nonThemes';
38+
});
39+
40+
const numberOfThemeExtesions = themes && themes.length;
41+
this.issueReporterModel.update({ numberOfThemeExtesions, enabledNonThemeExtesions: nonThemes, allExtensions: installedExtensions });
42+
this.updateExtensionTable(nonThemes, numberOfThemeExtesions);
43+
if (this.disableExtensions || installedExtensions.length === 0) {
44+
(<HTMLButtonElement>this.getElementById('disableExtensions')).disabled = true;
45+
}
46+
47+
this.updateExtensionSelector(installedExtensions);
48+
}
49+
50+
private async sendReporterMenu(extension: IssueReporterExtensionData): Promise<IssueReporterData | undefined> {
51+
try {
52+
const data = await this.issueMainService.$sendReporterMenu(extension.id, extension.name);
53+
return data;
54+
} catch (e) {
55+
console.error(e);
56+
return undefined;
57+
}
58+
}
59+
60+
public override setEventHandlers(): void {
61+
super.setEventHandlers();
62+
this.previewButton.onDidClick(async () => {
63+
this.delayedSubmit.trigger(async () => {
64+
this.createIssue();
65+
});
66+
});
67+
68+
this.addEventListener('disableExtensions', 'click', () => {
69+
this.issueMainService.$reloadWithExtensionsDisabled();
70+
});
71+
72+
this.addEventListener('extensionBugsLink', 'click', (e: Event) => {
73+
const url = (<HTMLElement>e.target).innerText;
74+
windowOpenNoOpener(url);
75+
});
76+
77+
this.addEventListener('disableExtensions', 'keydown', (e: Event) => {
78+
e.stopPropagation();
79+
if ((e as KeyboardEvent).key === "Enter" || (e as KeyboardEvent).key === " ") {
80+
this.issueMainService.$reloadWithExtensionsDisabled();
81+
}
82+
});
83+
84+
this.window.document.onkeydown = async (e: KeyboardEvent) => {
85+
const cmdOrCtrlKey = isMacintosh ? e.metaKey : e.ctrlKey;
86+
// Cmd/Ctrl+Enter previews issue and closes window
87+
if (cmdOrCtrlKey && e.key === "Enter") {
88+
this.delayedSubmit.trigger(async () => {
89+
if (await this.createIssue()) {
90+
this.close();
91+
}
92+
});
93+
}
94+
95+
// Cmd/Ctrl + w closes issue window
96+
if (cmdOrCtrlKey && e.key === "w") {
97+
e.stopPropagation();
98+
e.preventDefault();
99+
100+
const issueTitle = (<HTMLInputElement>this.getElementById('issue-title'))!.value;
101+
const { issueDescription } = this.issueReporterModel.getData();
102+
if (!this.hasBeenSubmitted && (issueTitle || issueDescription)) {
103+
// fire and forget
104+
this.issueMainService.$showConfirmCloseDialog();
105+
} else {
106+
this.close();
107+
}
108+
}
109+
110+
// Cmd/Ctrl + zooms in
111+
if (cmdOrCtrlKey && e.key === "+") {
112+
// zoomIn(this.window);
113+
}
114+
115+
// Cmd/Ctrl - zooms out
116+
if (cmdOrCtrlKey && e.key === "-") {
117+
// zoomOut(this.window);
118+
}
119+
120+
// With latest electron upgrade, cmd+a is no longer propagating correctly for inputs in this window on mac
121+
// Manually perform the selection
122+
if (isMacintosh) {
123+
if (cmdOrCtrlKey && e.key === "a" && e.target) {
124+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
125+
(<HTMLInputElement>e.target).select();
126+
}
127+
}
128+
}
129+
};
130+
}
131+
132+
private updateExtensionSelector(extensions: IssueReporterExtensionData[]): void {
133+
interface IOption {
134+
name: string;
135+
id: string;
136+
}
137+
138+
const extensionOptions: IOption[] = extensions.map(extension => {
139+
return {
140+
name: extension.displayName || extension.name || '',
141+
id: extension.id
142+
};
143+
});
144+
145+
// Sort extensions by name
146+
extensionOptions.sort((a, b) => {
147+
const aName = a.name.toLowerCase();
148+
const bName = b.name.toLowerCase();
149+
if (aName > bName) {
150+
return 1;
151+
}
152+
153+
if (aName < bName) {
154+
return -1;
155+
}
156+
157+
return 0;
158+
});
159+
160+
const makeOption = (extension: IOption, selectedExtension?: IssueReporterExtensionData): HTMLOptionElement => {
161+
const selected = selectedExtension && extension.id === selectedExtension.id;
162+
return $<HTMLOptionElement>('option', {
163+
'value': extension.id,
164+
'selected': selected || ''
165+
}, extension.name);
166+
};
167+
168+
const extensionsSelector = this.getElementById<HTMLSelectElement>('extension-selector');
169+
if (extensionsSelector) {
170+
const { selectedExtension } = this.issueReporterModel.getData();
171+
reset(extensionsSelector, this.makeOption('', localize('selectExtension', "Select extension"), true), ...extensionOptions.map(extension => makeOption(extension, selectedExtension)));
172+
173+
if (!selectedExtension) {
174+
extensionsSelector.selectedIndex = 0;
175+
}
176+
177+
this.addEventListener('extension-selector', 'change', async (e: Event) => {
178+
this.clearExtensionData();
179+
const selectedExtensionId = (<HTMLInputElement>e.target).value;
180+
this.selectedExtension = selectedExtensionId;
181+
const extensions = this.issueReporterModel.getData().allExtensions;
182+
const matches = extensions.filter(extension => extension.id === selectedExtensionId);
183+
if (matches.length) {
184+
this.issueReporterModel.update({ selectedExtension: matches[0] });
185+
const selectedExtension = this.issueReporterModel.getData().selectedExtension;
186+
if (selectedExtension) {
187+
await this.sendReporterMenu(selectedExtension);
188+
} else {
189+
this.issueReporterModel.update({ selectedExtension: undefined });
190+
this.clearSearchResults();
191+
this.clearExtensionData();
192+
this.validateSelectedExtension();
193+
this.updateExtensionStatus(matches[0]);
194+
}
195+
}
196+
});
197+
}
198+
199+
this.addEventListener('problem-source', 'change', (_) => {
200+
this.validateSelectedExtension();
201+
});
202+
}
203+
}

src/vs/code/electron-sandbox/issue/issueReporterMain.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { safeInnerHtml } from 'vs/base/browser/dom';
77
import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded
88
import { isLinux, isWindows } from 'vs/base/common/platform';
9-
import BaseHtml from 'vs/code/electron-sandbox/issue/issueReporterPage';
9+
import BaseHtml from 'vs/code/browser/issue/issueReporterPage';
1010
import 'vs/css!./media/issueReporter';
1111
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
1212
import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions';
@@ -18,7 +18,7 @@ import { registerMainProcessRemoteService } from 'vs/platform/ipc/electron-sandb
1818
import { IIssueMainService, IssueReporterWindowConfiguration } from 'vs/platform/issue/common/issue';
1919
import { INativeHostService } from 'vs/platform/native/common/native';
2020
import { NativeHostService } from 'vs/platform/native/common/nativeHostService';
21-
import { IssueReporter } from './issueReporterService';
21+
import { IssueReporter2 } from 'vs/code/electron-sandbox/issue/issueReporterService2';
2222
import { mainWindow } from 'vs/base/browser/window';
2323

2424
export function startup(configuration: IssueReporterWindowConfiguration) {
@@ -29,7 +29,7 @@ export function startup(configuration: IssueReporterWindowConfiguration) {
2929

3030
const instantiationService = initServices(configuration.windowId);
3131

32-
const issueReporter = instantiationService.createInstance(IssueReporter, configuration);
32+
const issueReporter = instantiationService.createInstance(IssueReporter2, configuration);
3333
issueReporter.render();
3434
mainWindow.document.body.style.display = 'block';
3535
issueReporter.setInitialFocus();

src/vs/code/electron-sandbox/issue/issueReporterService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { isLinuxSnap, isMacintosh } from 'vs/base/common/platform';
1616
import { escape } from 'vs/base/common/strings';
1717
import { ThemeIcon } from 'vs/base/common/themables';
1818
import { URI } from 'vs/base/common/uri';
19-
import { IssueReporterModel, IssueReporterData as IssueReporterModelData } from 'vs/code/electron-sandbox/issue/issueReporterModel';
19+
import { IssueReporterModel, IssueReporterData as IssueReporterModelData } from 'vs/code/browser/issue/issueReporterModel';
2020
import { localize } from 'vs/nls';
2121
import { isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
2222
import { IIssueMainService, IssueReporterData, IssueReporterExtensionData, IssueReporterStyles, IssueReporterWindowConfiguration, IssueType } from 'vs/platform/issue/common/issue';

0 commit comments

Comments
 (0)