ghtui 0.2.0

A keyboard-driven terminal client for GitHub, with a pull request diff viewer that goes further than GitHub's
//! Who and what a comment can mention in a repository: the people it can
//! assign, and its recently updated issues and pull requests.

use serde::Deserialize;

use crate::api::model::RepoId;
use crate::api::{ApiError, GitHub};

/// What the comment box offers after `@` and `#` in a repository.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Mentionable {
    /// Its assignable users' logins.
    pub users: Vec<String>,
    /// Its issues and pull requests, most recently updated first: number
    /// and title.
    pub issues: Vec<(u64, String)>,
}

impl GitHub {
    /// Who and what `repo` lets a comment mention: one page of each,
    /// revalidated with ETags like any REST page.
    pub async fn mentionable(&self, repo: &RepoId) -> Result<Mentionable, ApiError> {
        #[derive(Deserialize)]
        struct Issue {
            number: u64,
            title: String,
        }
        let base = format!("/repos/{}/{}", repo.owner, repo.name);
        let users = format!("{base}/assignees?per_page=100");
        let issues = format!("{base}/issues?state=all&sort=updated&per_page=100");
        let (users, issues) = futures::join!(
            self.rest_get(&users, format!("{repo}'s assignable users")),
            self.rest_get(&issues, format!("{repo}'s issues")),
        );
        let users: Vec<crate::api::browse::UserLogin> = serde_json::from_str(&users?)?;
        let issues: Vec<Issue> = serde_json::from_str(&issues?)?;
        Ok(Mentionable {
            users: users.into_iter().map(|u| u.login).collect(),
            issues: issues.into_iter().map(|i| (i.number, i.title)).collect(),
        })
    }
}