1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use anyhow::Context;
use forgejo_api::structs::{CreateIssueCommentOption, IssueListIssuesQuery};

use crate::actions::issue::display_issue;

use crate::actions::text_manipulation::{edit_prompt_for, select_prompt_for};
use crate::actions::GeneralArgs;
use crate::render::spinner::spin_until_ready;
use crate::render::ui::fuzzy_select_with_key;
use crate::types::context::BergContext;
use crate::types::git::OwnerRepo;

use clap::Parser;

/// Add a comment to selected issue
#[derive(Parser, Debug)]
pub struct CommentIssueArgs {}

impl CommentIssueArgs {
    pub async fn run(self, general_args: GeneralArgs) -> anyhow::Result<()> {
        let _ = general_args;
        let ctx = BergContext::new(self).await?;
        let OwnerRepo { owner, repo } = ctx.owner_repo()?;
        let issues_list = spin_until_ready(ctx.client.issue_list_issues(
            owner.as_str(),
            repo.as_str(),
            IssueListIssuesQuery::default(),
        ))
        .await
        .map_err(anyhow::Error::from)?;

        let selected_issue =
            fuzzy_select_with_key(&issues_list, select_prompt_for("issue"), display_issue)?;

        let (nr, title) = {
            (
                selected_issue.id.context("Selected issue had no id")?,
                selected_issue
                    .title
                    .as_ref()
                    .cloned()
                    .context("Selected issue had no title")?,
            )
        };

        let body = get_comment_input(title)?;
        let comment = ctx
            .client
            .issue_create_comment(
                owner.as_str(),
                repo.as_str(),
                nr,
                CreateIssueCommentOption {
                    body,
                    updated_at: None,
                },
            )
            .await?;

        tracing::debug!("{comment:?}");

        Ok(())
    }
}

fn get_comment_input(issue_title: impl AsRef<str>) -> anyhow::Result<String> {
    let new_comment = inquire::Editor::new(edit_prompt_for("a comment").as_str())
        .with_predefined_text(
            format!("Write a comment for issue \"{}\"", issue_title.as_ref()).as_str(),
        )
        .prompt()?;
    Ok(new_comment)
}