export async function pickProject()

in src/desktop/gitlab/pick_project.ts [10:79]


export async function pickProject(
  gitlabService: GitLabService,
): Promise<GqlProjectWithRepoInfo | undefined> {
  const other = {
    label: '$(globe) Other',
    description: 'Enter the path of a public project',
    alwaysShow: true,
    other: true as const,
  };

  type Item = vscode.QuickPickItem & { project: GqlProjectWithRepoInfo; other: false };
  type ItemOrOther = Item | typeof other;

  // Return the user's projects which match the query
  async function getItems(query?: string): Promise<ItemOrOther[]> {
    const result = await gitlabService.fetchFromApi(
      getProjectsWithRepositoryInfo({ search: query }),
    );
    const items = result.projects.nodes.map(project => ({
      // We have to use `namespaceWithPath`. `project.name` can be arbitrary text and VS Code filters the items based on `query`
      // For example, we search for `test`, API returns project {name: 'Project', namespaceWithPath: 'group/test'}, if we use `project.name`
      // VS Code won't find the `test` string and won't show the item to the user
      label: `$(repo) ${project.fullPath}`,
      project,
      other: false as const,
    }));
    return [other, ...items];
  }

  // Lookup a specific project by path
  async function lookupItem(path: string): Promise<GqlProjectWithRepoInfo | undefined> {
    const { project } = await gitlabService.fetchFromApi(getProjectWithRepositoryInfo(path));

    if (!project) await vscode.window.showWarningMessage(`Cannot find project with path '${path}'`);
    return project;
  }

  // Show the quick pick
  const { picked, query } = await pickWithQuery(
    {
      ignoreFocusOut: true,
      title: 'Select GitLab project',
    },
    getItems,
  );

  // If the user picked an item other than `other`, return it
  if (picked && !picked.other) {
    return picked.project;
  }

  // If the user typed something in, resolve that as a project without prompting
  // them for input. This provides a similar UX to 'Git: Switch Branch'.
  if (query) {
    return lookupItem(query);
  }

  // The user selected 'Other' without typing anything in. Prompt them to
  // provide the path of a project.
  const input = await vscode.window.showInputBox({
    ignoreFocusOut: true,
    prompt: 'Enter the path of a GitLab project',
  });
  if (input) {
    return lookupItem(input);
  }

  // The user canceled the input box
  return undefined;
}