Skip to content
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,12 @@
"scope": "application",
"description": "Show the submit and test shortcuts in editor or not."
},
"leetcode.enableSideMode": {
"type": "boolean",
"default": true,
"scope": "application",
"description": "Determine whether to group all webview pages into Column 2 when solving problems."
},
"leetcode.nodePath": {
"type": "string",
"default": "node",
Expand Down Expand Up @@ -338,6 +344,6 @@
"markdown-it": "^8.4.2",
"require-from-string": "^2.0.2",
"unescape-js": "^1.1.1",
"vsc-leetcode-cli": "2.6.3"
"vsc-leetcode-cli": "2.6.4"
}
}
15 changes: 12 additions & 3 deletions src/commands/show.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@ import { IProblem, IQuickItemEx, languages, ProblemState } from "../shared";
import { DialogOptions, DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils";
import { selectWorkspaceFolder } from "../utils/workspaceUtils";
import * as wsl from "../utils/wslUtils";
import { leetCodePreviewProvider } from "../webview/leetCodePreviewProvider";
import { leetCodeSolutionProvider } from "../webview/leetCodeSolutionProvider";
import * as list from "./list";

export async function previewProblem(node: IProblem, isSideMode: boolean = false): Promise<void> {
const descString: string = await leetCodeExecutor.getDescription(node);
leetCodePreviewProvider.show(descString, node, isSideMode);
}

export async function showProblem(node?: LeetCodeNode): Promise<void> {
if (!node) {
return;
Expand Down Expand Up @@ -51,7 +57,7 @@ export async function showSolution(node?: LeetCodeNode): Promise<void> {
}
try {
const solution: string = await leetCodeExecutor.showSolution(node, language);
await leetCodeSolutionProvider.show(unescapeJS(solution), node);
leetCodeSolutionProvider.show(unescapeJS(solution), node);
} catch (error) {
leetCodeChannel.appendLine(error.toString());
await promptForOpenOutputChannel("Failed to fetch the top voted solution. Please open the output channel for details.", DialogType.error);
Expand Down Expand Up @@ -95,7 +101,7 @@ async function showProblemInternal(node: IProblem): Promise<void> {
// SUGGESTION: group config retriving into one file
const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode");
let outDir: string = await selectWorkspaceFolder();
let relativePath: string = (leetCodeConfig.get<string>("outputFolder") || "").trim();
let relativePath: string = (leetCodeConfig.get<string>("outputFolder", "")).trim();
const matchResult: RegExpMatchArray | null = relativePath.match(/\$\{(.*?)\}/);
if (matchResult) {
const resolvedPath: string | undefined = await resolveRelativePath(matchResult[1].toLocaleLowerCase(), node, language);
Expand All @@ -111,7 +117,10 @@ async function showProblemInternal(node: IProblem): Promise<void> {

const originFilePath: string = await leetCodeExecutor.showProblem(node, language, outDir);
const filePath: string = wsl.useWsl() ? await wsl.toWinPath(originFilePath) : originFilePath;
await vscode.window.showTextDocument(vscode.Uri.file(filePath), { preview: false, viewColumn: vscode.ViewColumn.One });
await Promise.all([
vscode.window.showTextDocument(vscode.Uri.file(filePath), { preview: false, viewColumn: vscode.ViewColumn.One }),
leetCodeConfig.get<boolean>("enableSideMode", true) ? previewProblem(node, true) : Promise.resolve(),
]);
} catch (error) {
await promptForOpenOutputChannel("Failed to show the problem. Please open the output channel for details.", DialogType.error);
}
Expand Down
2 changes: 1 addition & 1 deletion src/commands/submit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export async function submitSolution(uri?: vscode.Uri): Promise<void> {

try {
const result: string = await leetCodeExecutor.submitSolution(filePath);
await leetCodeSubmissionProvider.show(result);
leetCodeSubmissionProvider.show(result);
} catch (error) {
await promptForOpenOutputChannel("Failed to submit the solution. Please open the output channel for details.", DialogType.error);
}
Expand Down
2 changes: 1 addition & 1 deletion src/commands/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export async function testSolution(uri?: vscode.Uri): Promise<void> {
if (!result) {
return;
}
await leetCodeSubmissionProvider.show(result);
leetCodeSubmissionProvider.show(result);
} catch (error) {
await promptForOpenOutputChannel("Failed to test the solution. Please open the output channel for details.", DialogType.error);
}
Expand Down
2 changes: 1 addition & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
vscode.commands.registerCommand("leetcode.signout", () => leetCodeManager.signOut()),
vscode.commands.registerCommand("leetcode.selectSessions", () => session.selectSession()),
vscode.commands.registerCommand("leetcode.createSession", () => session.createSession()),
vscode.commands.registerCommand("leetcode.previewProblem", (node: LeetCodeNode) => leetCodePreviewProvider.show(node)),
vscode.commands.registerCommand("leetcode.previewProblem", (node: LeetCodeNode) => show.previewProblem(node)),
vscode.commands.registerCommand("leetcode.showProblem", (node: LeetCodeNode) => show.showProblem(node)),
vscode.commands.registerCommand("leetcode.searchProblem", () => show.searchProblem()),
vscode.commands.registerCommand("leetcode.showSolution", (node: LeetCodeNode) => show.showSolution(node)),
Expand Down
17 changes: 12 additions & 5 deletions src/webview/LeetCodeWebview.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Copyright (c) jdneo. All rights reserved.
// Licensed under the MIT license.

import { ConfigurationChangeEvent, Disposable, ViewColumn, WebviewPanel, window, workspace } from "vscode";
import { commands, ConfigurationChangeEvent, Disposable, ViewColumn, WebviewPanel, window, workspace } from "vscode";
import { markdownEngine } from "./markdownEngine";

export abstract class LeetCodeWebview implements Disposable {

protected readonly viewType: string = "leetcode.webview";
protected panel: WebviewPanel | undefined;
private listeners: Disposable[] = [];

Expand All @@ -16,9 +17,9 @@ export abstract class LeetCodeWebview implements Disposable {
}

protected showWebviewInternal(): void {
const { viewType, title, viewColumn, preserveFocus } = this.getWebviewOption();
const { title, viewColumn, preserveFocus } = this.getWebviewOption();
if (!this.panel) {
this.panel = window.createWebviewPanel(viewType, title, { viewColumn, preserveFocus }, {
this.panel = window.createWebviewPanel(this.viewType, title, { viewColumn, preserveFocus }, {
enableScripts: true,
enableCommandUris: true,
enableFindWidget: true,
Expand All @@ -30,7 +31,14 @@ export abstract class LeetCodeWebview implements Disposable {
workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.listeners);
} else {
this.panel.title = title;
this.panel.reveal(viewColumn, preserveFocus);
if (viewColumn === ViewColumn.Two) {
// Make sure second group exists. See vscode#71608 issue
commands.executeCommand("workbench.action.focusSecondEditorGroup").then(() => {
this.panel!.reveal(viewColumn, preserveFocus);
});
} else {
this.panel.reveal(viewColumn, preserveFocus);
}
}
this.panel.webview.html = this.getWebviewContent();
}
Expand All @@ -57,7 +65,6 @@ export abstract class LeetCodeWebview implements Disposable {
}

export interface ILeetCodeWebviewOption {
viewType: string;
title: string;
viewColumn: ViewColumn;
preserveFocus?: boolean;
Expand Down
42 changes: 31 additions & 11 deletions src/webview/leetCodePreviewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,47 @@
// Licensed under the MIT license.

import { commands, ViewColumn } from "vscode";
import { leetCodeExecutor } from "../leetCodeExecutor";
import { IProblem } from "../shared";
import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview";
import { markdownEngine } from "./markdownEngine";

class LeetCodePreviewProvider extends LeetCodeWebview {

protected readonly viewType: string = "leetcode.preview";
private node: IProblem;
private description: IDescription;
private sideMode: boolean = false;

public async show(node: IProblem): Promise<void> {
this.description = this.parseDescription(await leetCodeExecutor.getDescription(node), node);
public isSideMode(): boolean {
return this.sideMode;
}

public show(descString: string, node: IProblem, isSideMode: boolean = false): void {
this.description = this.parseDescription(descString, node);
this.node = node;
this.sideMode = isSideMode;
this.showWebviewInternal();
if (this.sideMode) {
// Hide the side bar for better view area
commands.executeCommand("workbench.action.focusSideBar").then(() => {
commands.executeCommand("workbench.action.toggleSidebarVisibility");
});
}
}

protected getWebviewOption(): ILeetCodeWebviewOption {
return {
viewType: "leetcode.preview",
title: `${this.node.name}: Preview`,
viewColumn: ViewColumn.One,
};
if (!this.sideMode) {
return {
title: `${this.node.name}: Preview`,
viewColumn: ViewColumn.One,
};
} else {
return {
title: "Description",
viewColumn: ViewColumn.Two,
preserveFocus: true,
};
}
}

protected getWebviewContent(): string {
Expand Down Expand Up @@ -84,18 +103,18 @@ class LeetCodePreviewProvider extends LeetCodeWebview {
<html>
<head>
${markdownEngine.getStyles()}
${button.style}
${!this.sideMode ? button.style : ""}
</head>
<body>
${head}
${info}
${tags}
${companies}
${body}
${button.element}
${!this.sideMode ? button.element : ""}
<script>
const vscode = acquireVsCodeApi();
${button.script}
${!this.sideMode ? button.script : ""}
</script>
</body>
</html>
Expand All @@ -106,6 +125,7 @@ class LeetCodePreviewProvider extends LeetCodeWebview {
super.onDidDisposeWebview();
delete this.node;
delete this.description;
this.sideMode = false;
}

protected async onDidReceiveMessage(message: IWebViewMessage): Promise<void> {
Expand Down
24 changes: 18 additions & 6 deletions src/webview/leetCodeSolutionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,35 @@

import { ViewColumn } from "vscode";
import { IProblem } from "../shared";
import { leetCodePreviewProvider } from "./leetCodePreviewProvider";
import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview";
import { markdownEngine } from "./markdownEngine";

class LeetCodeSolutionProvider extends LeetCodeWebview {

protected readonly viewType: string = "leetcode.solution";
private solution: Solution;
private sideMode: boolean = false;

public async show(solutionString: string, problem: IProblem): Promise<void> {
public show(solutionString: string, problem: IProblem): void {
this.solution = this.parseSolution(solutionString, problem);
this.sideMode = leetCodePreviewProvider.isSideMode();
this.showWebviewInternal();
}

protected getWebviewOption(): ILeetCodeWebviewOption {
return {
viewType: "leetcode.solution",
title: `${this.solution.problem}: Solution`,
viewColumn: ViewColumn.One,
};
if (!this.sideMode) {
return {
title: `${this.solution.problem}: Solution`,
viewColumn: ViewColumn.One,
};
} else {
return {
title: "Solution",
viewColumn: ViewColumn.Two,
preserveFocus: true,
};
}
}

protected getWebviewContent(): string {
Expand Down Expand Up @@ -55,6 +66,7 @@ class LeetCodeSolutionProvider extends LeetCodeWebview {
protected onDidDisposeWebview(): void {
super.onDidDisposeWebview();
delete this.solution;
this.sideMode = false;
}

private parseSolution(raw: string, problem: IProblem): Solution {
Expand Down
4 changes: 2 additions & 2 deletions src/webview/leetCodeSubmissionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import { markdownEngine } from "./markdownEngine";

class LeetCodeSubmissionProvider extends LeetCodeWebview {

protected readonly viewType: string = "leetcode.submission";
private result: string;

public async show(result: string): Promise<void> {
public show(result: string): void {
this.result = result;
this.showWebviewInternal();
}

protected getWebviewOption(): ILeetCodeWebviewOption {
return {
viewType: "leetcode.submission",
title: "Submission",
viewColumn: ViewColumn.Two,
};
Expand Down