Skip to content

Commit f77737d

Browse files
xuzaixianjdneo
authored andcommitted
Add Click the tree explorer should open the topic (#132) (#186)
1 parent b85611b commit f77737d

6 files changed

+144
-3
lines changed

package.json

+15
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"onCommand:leetcode.createSession",
3434
"onCommand:leetcode.refreshExplorer",
3535
"onCommand:leetcode.showProblem",
36+
"onCommand:leetcode.previewProblem",
3637
"onCommand:leetcode.searchProblem",
3738
"onCommand:leetcode.testSolution",
3839
"onCommand:leetcode.submitSolution",
@@ -94,6 +95,11 @@
9495
"title": "Show Problem",
9596
"category": "LeetCode"
9697
},
98+
{
99+
"command": "leetcode.previewProblem",
100+
"title": "Preview Problem",
101+
"category": "LeetCode"
102+
},
97103
{
98104
"command": "leetcode.searchProblem",
99105
"title": "Search Problem",
@@ -164,12 +170,21 @@
164170
"command": "leetcode.showProblem",
165171
"when": "view == leetCodeExplorer && viewItem == problem",
166172
"group": "leetcode@1"
173+
},
174+
{
175+
"command": "leetcode.previewProblem",
176+
"when": "view == leetCodeExplorer && viewItem == problem",
177+
"group": "leetcode@1"
167178
}
168179
],
169180
"commandPalette": [
170181
{
171182
"command": "leetcode.showProblem",
172183
"when": "never"
184+
},
185+
{
186+
"command": "leetcode.previewProblem",
187+
"when": "never"
173188
}
174189
],
175190
"explorer/context": [

src/explorer/LeetCodeNode.ts

+10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) jdneo. All rights reserved.
22
// Licensed under the MIT license.
33

4+
import { Command } from "vscode";
45
import { IProblem, ProblemState } from "../shared";
56

67
export class LeetCodeNode {
@@ -48,4 +49,13 @@ export class LeetCodeNode {
4849
public get parentName(): string {
4950
return this.parentNodeName;
5051
}
52+
53+
public get previewCommand(): Command {
54+
return {
55+
title: "Preview Problem",
56+
command: "leetcode.previewProblem",
57+
arguments: [this],
58+
};
59+
}
60+
5161
}

src/explorer/LeetCodeTreeDataProvider.ts

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider<LeetCod
5252
collapsibleState: element.isProblem ? vscode.TreeItemCollapsibleState.None : vscode.TreeItemCollapsibleState.Collapsed,
5353
contextValue: element.isProblem ? "problem" : element.id.toLowerCase(),
5454
iconPath: this.parseIconPathFromProblemState(element),
55+
command: element.isProblem ? element.previewCommand : undefined,
5556
};
5657
}
5758

src/extension.ts

+4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { LeetCodeTreeDataProvider } from "./explorer/LeetCodeTreeDataProvider";
1515
import { leetCodeChannel } from "./leetCodeChannel";
1616
import { leetCodeExecutor } from "./leetCodeExecutor";
1717
import { leetCodeManager } from "./leetCodeManager";
18+
import { leetCodePreviewProvider } from "./leetCodePreviewProvider";
1819
import { leetCodeResultProvider } from "./leetCodeResultProvider";
1920
import { leetCodeStatusBarItem } from "./leetCodeStatusBarItem";
2021

@@ -29,11 +30,13 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
2930
});
3031

3132
const leetCodeTreeDataProvider: LeetCodeTreeDataProvider = new LeetCodeTreeDataProvider(context);
33+
leetCodePreviewProvider.initialize(context);
3234
leetCodeResultProvider.initialize(context);
3335

3436
context.subscriptions.push(
3537
leetCodeStatusBarItem,
3638
leetCodeChannel,
39+
leetCodePreviewProvider,
3740
leetCodeResultProvider,
3841
vscode.window.createTreeView("leetCodeExplorer", { treeDataProvider: leetCodeTreeDataProvider, showCollapseAll: true }),
3942
vscode.languages.registerCodeLensProvider({ scheme: "file" }, codeLensProvider),
@@ -43,6 +46,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
4346
vscode.commands.registerCommand("leetcode.signout", () => leetCodeManager.signOut()),
4447
vscode.commands.registerCommand("leetcode.selectSessions", () => session.selectSession()),
4548
vscode.commands.registerCommand("leetcode.createSession", () => session.createSession()),
49+
vscode.commands.registerCommand("leetcode.previewProblem", (node: LeetCodeNode) => leetCodePreviewProvider.preview(node)),
4650
vscode.commands.registerCommand("leetcode.showProblem", (node: LeetCodeNode) => show.showProblem(node)),
4751
vscode.commands.registerCommand("leetcode.searchProblem", () => show.searchProblem()),
4852
vscode.commands.registerCommand("leetcode.refreshExplorer", () => leetCodeTreeDataProvider.refresh()),

src/leetCodeExecutor.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,22 @@ class LeetCodeExecutor {
7575
);
7676
}
7777

78-
public async showProblem(node: IProblem, language: string, outDir: string): Promise<string> {
79-
const fileName: string = genFileName(node, language);
78+
public async showProblem(problemNode: IProblem, language: string, outDir: string): Promise<string> {
79+
const fileName: string = genFileName(problemNode, language);
8080
const filePath: string = path.join(outDir, fileName);
8181

8282
if (!await fse.pathExists(filePath)) {
83-
const codeTemplate: string = await this.executeCommandWithProgressEx("Fetching problem data...", "node", [await this.getLeetCodeBinaryPath(), "show", node.id, "-cx", "-l", language]);
83+
const codeTemplate: string = await this.executeCommandWithProgressEx("Fetching problem data...", "node", [await this.getLeetCodeBinaryPath(), "show", problemNode.id, "-cx", "-l", language]);
8484
await fse.writeFile(filePath, codeTemplate);
8585
}
8686

8787
return filePath;
8888
}
8989

90+
public async getDescription(problemNode: IProblem): Promise<string> {
91+
return await this.executeCommandWithProgressEx("Fetching problem description...", "node", [await this.getLeetCodeBinaryPath(), "show", problemNode.id, "-x"]);
92+
}
93+
9094
public async listSessions(): Promise<string> {
9195
return await this.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "session"]);
9296
}

src/leetCodePreviewProvider.ts

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import { commands, Disposable, ExtensionContext, ViewColumn, WebviewPanel, window } from "vscode";
2+
import { leetCodeExecutor } from "./leetCodeExecutor";
3+
import { IProblem } from "./shared";
4+
class LeetCodePreviewProvider implements Disposable {
5+
6+
private context: ExtensionContext;
7+
private panel: WebviewPanel | undefined;
8+
9+
public initialize(context: ExtensionContext): void {
10+
this.context = context;
11+
}
12+
13+
public async preview(node: IProblem): Promise<void> {
14+
if (!this.panel) {
15+
const panelType: string = "previewProblem";
16+
const panelTitle: string = node.name;
17+
this.panel = window.createWebviewPanel(panelType, panelTitle, ViewColumn.Active, {
18+
enableScripts: true,
19+
enableCommandUris: true,
20+
enableFindWidget: true,
21+
retainContextWhenHidden: true,
22+
});
23+
}
24+
25+
this.panel.onDidDispose(() => {
26+
this.panel = undefined;
27+
}, null, this.context.subscriptions);
28+
29+
this.panel.webview.onDidReceiveMessage(async (message: IWebViewMessage) => {
30+
switch (message.command) {
31+
case "ShowProblem":
32+
await commands.executeCommand("leetcode.showProblem", node);
33+
this.dispose();
34+
return;
35+
}
36+
});
37+
this.panel.webview.html = await this.provideHtmlContent(node);
38+
}
39+
40+
public dispose(): void {
41+
if (this.panel) {
42+
this.panel.dispose();
43+
}
44+
}
45+
46+
public async provideHtmlContent(node: IProblem): Promise<string> {
47+
return await this.renderHTML(node);
48+
}
49+
50+
private async renderHTML(node: IProblem): Promise<string> {
51+
const description: string = await leetCodeExecutor.getDescription(node);
52+
const descriptionHTML: string = description.replace(/\n/g, "<br>");
53+
const htmlTemplate: string = `
54+
<!DOCTYPE html>
55+
<html>
56+
<head>
57+
<meta charset="UTF-8">
58+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
59+
<title>Preview Problem</title>
60+
</head>
61+
<style>
62+
#solve {
63+
position: fixed;
64+
bottom: 1rem;
65+
right: 1rem;
66+
border: 0;
67+
margin: 1rem 0;
68+
padding: 0.2rem 1rem;
69+
color: white;
70+
background-color: var(--vscode-button-background);
71+
}
72+
#solve:hover {
73+
background-color: var(--vscode-button-hoverBackground);
74+
}
75+
#solve:active {
76+
border: 0;
77+
}
78+
</style>
79+
<body>
80+
<div >
81+
${ descriptionHTML}
82+
</div>
83+
<button id="solve">Code Now</button>
84+
<script>
85+
(function() {
86+
const vscode = acquireVsCodeApi();
87+
let button = document.getElementById('solve');
88+
button.onclick = solveHandler;
89+
function solveHandler() {
90+
vscode.postMessage({
91+
command: 'ShowProblem',
92+
});
93+
}
94+
}());
95+
</script>
96+
</body>
97+
</html>
98+
`;
99+
return htmlTemplate;
100+
}
101+
102+
}
103+
export interface IWebViewMessage {
104+
command: string;
105+
}
106+
107+
export const leetCodePreviewProvider: LeetCodePreviewProvider = new LeetCodePreviewProvider();

0 commit comments

Comments
 (0)