Skip to content

Commit 4625a1e

Browse files
committed
Was able to dispose of the webview resources properly. We are able to show the current webview if it hidden by selecting our extension. Only one webview is created, if another file is wanted by the user, old webview is disposed and a new one is created to prevent any memory leaks.
1 parent cbdd3c2 commit 4625a1e

File tree

2 files changed

+79
-26
lines changed

2 files changed

+79
-26
lines changed

src/extension.ts

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,67 @@
11
import * as vscode from 'vscode';
22
import {createPanel} from './panel';
33
import { Parser } from './parser';
4+
import { Tree } from './types/tree';
5+
6+
let tree: Parser | undefined = undefined;
7+
let panel: vscode.WebviewPanel | undefined = undefined
8+
49

510
// This method is called when your extension is activated
611
// Your extension is activated the very first time the command is executed
7-
812
function activate(context: vscode.ExtensionContext) {
913

10-
let disposable = vscode.commands.registerCommand('react-labyrinth.helloWorld', function () {
11-
vscode.window.showInformationMessage('Hello World from React Labyrinth!');
12-
});
14+
// This is the column where Webview will be revealed to
15+
const columnToShowIn : vscode.ViewColumn | undefined = vscode.window.activeTextEditor
16+
? vscode.window.activeTextEditor.viewColumn
17+
: undefined;
18+
19+
20+
// Command that allows for User to select the root file of their React application.
21+
const pickFile: vscode.Disposable = vscode.commands.registerCommand('myExtension.pickFile', async () => {
22+
1323

14-
// pass in the command we want to register (refer to package.json)
15-
// let result = vscode.commands.registerCommand('myExtension.showPanel', () => {
16-
// // call helper func
17-
// createPanel(context);
18-
// });
24+
// Check if there is an existing webview panel, if so display it.
25+
if(panel) {
26+
panel.reveal(columnToShowIn)
27+
}
1928

20-
vscode.commands.registerCommand('myExtension.pickFile', async () => {
21-
const fileArray = await vscode.window.showOpenDialog({ canSelectFolders: false, canSelectFiles: true, canSelectMany: false });
29+
30+
// Opens window for the User to select the root file of React application
31+
const fileArray: vscode.Uri[] = await vscode.window.showOpenDialog({ canSelectFolders: false, canSelectFiles: true, canSelectMany: false });
2232

33+
34+
// Throw error message if no file was selected
2335
if (!fileArray || fileArray.length === 0) {
2436
vscode.window.showErrorMessage('No file selected');
2537
return;
2638
}
27-
28-
const tree = new Parser(fileArray[0].path);
39+
40+
41+
// Create Tree to be inserted into returned HTML
42+
tree = new Parser(fileArray[0].path);
2943
tree.parse();
30-
const data = tree.getTree();
31-
console.log('Data sent back: \n', data);
32-
createPanel(context, data);
44+
const data: Tree = tree.getTree();
45+
46+
47+
// Check if panel currently has a webview, if it does dispose of it and create another with updated root file selected.
48+
// Otherwise create a new webview to display root file selected.
49+
if(!panel) {
50+
panel = createPanel(context, data, columnToShowIn);
51+
} else {
52+
panel.dispose()
53+
panel = createPanel(context, data, columnToShowIn);
54+
}
3355
});
34-
context.subscriptions.push(disposable);
56+
57+
58+
// Command to show panel if it is hidden
59+
const showPanel: vscode.Disposable = vscode.commands.registerCommand('myExtension.showPanel', () => {
60+
panel.reveal(columnToShowIn)
61+
});
62+
63+
64+
context.subscriptions.push(pickFile, showPanel);
3565
}
3666

3767
// This method is called when your extension is deactivated

src/panel.ts

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,58 @@ import * as vscode from 'vscode';
22
import { getNonce } from './getNonce';
33
import { Tree } from './types/tree';
44

5-
export function createPanel(context: vscode.ExtensionContext, data: Tree) {
6-
// if the current panel exists, then reveal the column, else make one?
5+
let panel: vscode.WebviewPanel | undefined = undefined
6+
7+
export function createPanel(context: vscode.ExtensionContext, data: Tree, columnToShowIn: vscode.ViewColumn) {
78

89
// utilize method on vscode.window object to create webview
9-
const panel = vscode.window.createWebviewPanel(
10+
panel = vscode.window.createWebviewPanel(
1011
'reactLabyrinth',
1112
'React Labyrinth',
13+
1214
// create one new tab
1315
vscode.ViewColumn.One,
1416
{
1517
enableScripts: true,
1618
retainContextWhenHidden: true
1719
}
1820
);
21+
1922

23+
// Set the icon logo of extension webview
2024
panel.iconPath = vscode.Uri.joinPath(context.extensionUri, 'media', 'favicon.ico');
25+
26+
27+
// Set URI to be the path to bundle
28+
const bundlePath: vscode.Uri = vscode.Uri.joinPath(context.extensionUri, 'build', 'bundle.js');
2129

22-
const bundlePath = vscode.Uri.joinPath(context.extensionUri, 'build', 'bundle.js');
2330

2431
// set webview URI to pass into html script
25-
const bundleURI = panel.webview.asWebviewUri(bundlePath);
32+
const bundleURI: vscode.Uri = panel.webview.asWebviewUri(bundlePath);
33+
2634

2735
// render html of webview here
2836
panel.webview.html = createWebviewHTML(bundleURI, data);
2937

30-
// will need to use onDidDispose to clear cached data and reset tree when the webview and/or application is closed
3138

39+
// Listens for when webview is closed and disposes of webview resources
40+
panel.onDidDispose(
41+
() => {
42+
panel = undefined;
43+
},
44+
null,
45+
context.subscriptions
46+
);
47+
48+
49+
// Sends data to Flow.tsx to be displayed after parsed data is received
3250
panel.webview.onDidReceiveMessage(
3351
async (msg: any) => {
3452
switch (msg.type) {
3553
case 'onData':
3654
if (!msg.value) break;
3755
context.workspaceState.update('reactLabyrinth', msg.value);
38-
// console.log('msg.value from panel.js: ', msg.value);
56+
3957
panel.webview.postMessage(
4058
{
4159
type: 'parsed-data',
@@ -49,13 +67,18 @@ export function createPanel(context: vscode.ExtensionContext, data: Tree) {
4967
undefined,
5068
context.subscriptions
5169
);
70+
71+
return panel
5272
};
5373

74+
75+
5476
// getNonce generates a new random string each time ext is used to prevent external injection of foreign code into the html
55-
const nonce = getNonce();
77+
const nonce: string = getNonce();
78+
5679

5780
// function to create the HTML page for webview
58-
function createWebviewHTML(URI: vscode.Uri, initialData: Tree) {
81+
function createWebviewHTML(URI: vscode.Uri, initialData: Tree) : string {
5982
return (
6083
`
6184
<!DOCTYPE html>

0 commit comments

Comments
 (0)