Home GitMarker - QuickPick and Pagination
Post
Cancel

GitMarker - QuickPick and Pagination


Now and finally, let’s talk about this exciting capability. As for any software, we sometimes need to select existing items as if we were using a dropdown list. For example, with GitMarker, I needed to make it possible for the user to pick the result of searching GitHub repositories and select a Category for grouping them afterward. Luckily, the Visual Studio Code API provides us the QuickPickItem interface, which by definition represents an item that can be selected from a list of items.

The following examples are code blocks from search-result-manager class, designed to hold the whole logic for picking GitHub repositories and Categories.

It’s item picking time!


The simplest way to show pickeable items is using the vscode.window.showQuickPick method. It will require an array of objects containing an id and label, and that’s what I do when picking a category to be chosen right after the users pick the result of the repository search. Along with this argument, you can also provide the QuickPickOptions to configure the UI behavior as you want, and differently from the GitHub repository search results we will check next, I prevented the select-many behavior by setting canPickMany to false.

In addition, the showQuickPick method returns a Thenable, and the user can cancel the selection at any time or proceed with the choice, either by clicking on the quickPickItem or pressing enter on the selected one.

private async pickCategory(categories: Category[]) {
  const categoriesDetails = categories
  .map(categoryInfo => {
    return {
      id: categoryInfo.id,
      label: `📁 ${categoryInfo.name}`
    };
  });

  // picking a category from result list
  return await vscode.window.showQuickPick(categoriesDetails, {
    matchOnDescription: true,
    matchOnDetail: true,
    canPickMany: false,
    title: 'Please select the category for this bookmark'
  });
}

As can be seen, I also used an emoji to give a better look to the string that contains the label, once an option to provide an icon is not available.

Turning the page


When using GitMarker, you must search for a GitHub repository before you can bookmark it. This feature is the whole point of the extension, and I had a unique challenge: making a pagination system to support the thousands of repositories we can retrieve in a simple search. To do so, I couldn’t simply use the convenient showQuickPick, but instead, I used the vscode.window.createQuickPick method, which creates a QuickPick from a list of items of type T where T is a vscode.QuickPickItem. Thus, I’ve made a class I named * RepoPickItem* implementing vscode.QuickPickItem, with an additional Id property for the logic I intended.

class RepoPickItem implements vscode.QuickPickItem {
  constructor(public id: string, public label: string, public picked: boolean ) { }
}

QuickPick

When building a QuickPick object using the createQuickPick, you can set properties like step and totalSteps, essentials for implementing pagination, as I do with this method. Notice that these 2 properties are assigned elsewhere and are globally available in the search-result-manager class.

private buildQuickPicker() {
  let quickPick = vscode.window.createQuickPick<RepoPickItem>();
  quickPick.canSelectMany = true;
  quickPick.step = this.currentPage;
  quickPick.totalSteps = this.totalPages;
  quickPick.matchOnDescription = true;
  quickPick.matchOnDetail = true;
  return quickPick;
}

With the buildQuickPickButtons method, I’m dynamically building buttons of type QuickInputButton and considering the total and current pages. Hence I can return the proper combination of buttons, which in my case are either icons for going back, forward, or none.

Selected items

While navigating through the search results, you may want to pick one or many items from one page and then move to the next page and continue with a different selection. Regarding usability, I wanted to ensure that the selected items remain the same way you left them when going back and forth. For doing so, I stored the selected items in memory with the globally available pageSelectedItems. This class field is used by the events I’ll cover below.

onDidTriggerButton

This event is called when you hit the navigation arrows. With that, I can evaluate the type of button to identify whether to go back or forward with the pages. Also, I implemented logic to keep the result cached and only calling the githubApiClient for pages you haven’t gone through yet, which means that every back action works upon cached results.

onDidChangeSelection

This event is called for every item you check. It’s how I updated the pageSelectedItems for every selection.

onDidAccept

Last but not least, this event is the one that effects the whole selection, and it’s triggered when you click on [OK].

busy

It’s recommended to notify the user some async operation is ongoing, like when we’re searching for the next page. The QuickPick provides the boolean busy field you can set to true or false according to your need.

With the combination of all these events, fields, and methods, I could successfully implement a pagination system like this.


Check the whole search-result-manager class to see everything in greater detail.

This chapter ends the series of chapters I initially planned to explain how I built this extension. I might add some new content on uncovered subjects further, of course. However, I hope you have enjoyed it so far, and this could inspire you to build your extensions for Visual Studio Code.

Thanks for getting here!





This post is licensed under CC BY 4.0 by the author.