CompareFolders — a Visual Studio Code extension journey — Part IV

September 29, 2019

In the last post, we talked about how to add an icon to the activity bar and “attach” a view to it. How to use TreeDataProvider to present File System like view to show the diffs like files in directories.

Like promised, the post will includes an explanation about the product challenge and how to solve it.

The Challenge

In the last post, the extension was able to show only single hierarchy of differences. Means if a deep folder has differences the extension wasn’t be able to show it. This challenge, obviously, is not a vscode extension specifically but I splatted the commits so this refactor will “get” its own commit to isolate the logic and maybe will help to someone else with such task.

Back to the series’ format — vscode extension challenges, the extension should allow the users to refresh the folders view after some change has been made in a file / folder. So we’ll add a button to the panel’s “top bar” and when the user will click on it, the compare logic will run again and will refresh the view. Once the view refreshed, the extension will show an information popup about that.

A “top bar” button in the source control panel A “top bar” button in the source control panel

So

How to display a button in a view’s top bar?

In order to display a button we need some steps: We need to add the button as a “contributer” in the contributes section and specify the command that we want to run when it clicked. Therefore, we need to add that command to the commands section, also in the package.json. And finally, we need to register that command in the extension’s activation call.

Step 1

Add the “refresh” command in the commands section in package.json

1"commands": [
2 ...
3 {
4 "title": "Refresh",
5 "command": "foldersCompare.refresh",
6 "icon": "resources/refresh.svg"
7 }
8]

Step 2

Add the “refresh” button in the top bar in the contributes->menus section in package.json

1"contributes": {
2 ...
3 "menus": {
4 "view/title": [{
5 "command": "foldersCompare.refresh",
6 "group": "navigation"
7 }]
8 },
9}

command is the key of the command and group is the place we want to present the button inside the top bar. By default it will be presented under the “more” menu:

1SyNphHDTYWiX0ze 97vaJQ

Step 3

Register the command in the extension’s activation call

1export function activate(context: ExtensionContext) {
2 ...
3 commands.registerCommand(REFRESH, foldersCompareProvider.refresh);
4}

Step 4

Finally, we need to implement the “refresh” functionality and ask vscode refresh the view.

1refresh = (): void => {
2 try {
3 /*
4 get (from memory) the current path of the compared folder
5 and do the comparison again
6 */
7 this._diffs = compare(this.workspaceRoot, getComparedPath());
8 // ask vscode to refresh to view
9 this._onDidChangeTreeData.fire();
10 // show a message to the user
11 window.showInformationMessage('Source refreshed', 'Dismiss');
12 } catch (error) {
13 console.log(error);
14 }
15}

Notice that the onDidChangeTreeData.fire event shouldn’t call with arguments, otherwise, none of the functions (getChildren not getTreeItem) will be fired.

Notice also that the refresh method declared as an arrow function to bind it to the foldersCompareProvider instance. When vscode will invoke that function it will run in the context of the instance (Is that clear enough?)

Finally, we want to show an information message with a “dismiss” button to let them know that the sourced refreshed (in case the change in deep path and not visible in the UI right away)

And this is the result

Source code for this post

Have something to say? I’ll love to 👂

Original Post