codeberg-cli 0.4.9

CLI Tool for codeberg similar to gh and glab
Documentation
use crate::render::option::{option_debug_display, option_display};
use crate::render::ui::fuzzy_select_with_key;
use crate::types::context::BergContext;
use crate::{actions::GeneralArgs, render::datetime::render_datetime_and_info};
use anyhow::Context;
use forgejo_api::structs::{NotificationThread, NotifyGetListQuery};

use clap::Parser;
#[derive(Debug, Parser)]
pub struct ViewNotificationArgs {
    /// view specific notification if available
    pub id: Option<i64>,

    /// show everything about the notification if available
    #[arg(short, long)]
    pub all: bool,
}

impl ViewNotificationArgs {
    pub async fn run(self, general_args: GeneralArgs) -> anyhow::Result<()> {
        let _ = general_args;
        let ctx = BergContext::new(self, general_args).await?;

        let thread_id = if let Some(id) = ctx.args.id {
            id
        } else {
            fuzzy_select_with_key(
                &ctx.client
                    .notify_get_list(NotifyGetListQuery {
                        ..Default::default()
                    })
                    .await?
                    .iter()
                    .filter(|thread| thread.id.is_some())
                    .collect::<Vec<_>>(),
                "notification thread",
                |thread| {
                    option_display(
                        &thread
                            .subject
                            .as_ref()
                            .and_then(|subject| subject.title.as_ref()),
                    )
                },
            )
            .and_then(|thread| thread.id.context("No ID on selected thread"))?
        };

        let selected_notification_thread = ctx
            .client
            .notify_get_thread(thread_id.to_string().as_str())
            .await?;

        present_notification_thread_details(&ctx, selected_notification_thread);

        Ok(())
    }
}

fn present_notification_thread_details(
    ctx: &BergContext<ViewNotificationArgs>,
    notification_thread: NotificationThread,
) {
    let mut table = ctx.make_table();

    table
        .add_row(vec![
            String::from("Title"),
            option_display(
                &notification_thread
                    .subject
                    .as_ref()
                    .and_then(|subject| subject.title.as_ref()),
            ),
        ])
        .add_row(vec![
            String::from("URL"),
            option_display(
                &notification_thread
                    .subject
                    .as_ref()
                    .and_then(|subject| subject.html_url.as_ref()),
            ),
        ])
        .add_row(vec![
            String::from("Type"),
            option_display(
                &notification_thread
                    .subject
                    .as_ref()
                    .and_then(|subject| subject.r#type.as_ref()),
            ),
        ])
        .add_row(vec![
            String::from("State"),
            option_debug_display(
                &notification_thread
                    .subject
                    .as_ref()
                    .and_then(|subject| subject.state.as_ref()),
            ),
        ])
        .add_row(vec![
            "Unread",
            if notification_thread.unread.is_some_and(|is_true| is_true) {
                "Yes"
            } else {
                "No"
            },
        ])
        .add_row(vec![
            "Pinned",
            if notification_thread.pinned.is_some_and(|is_true| is_true) {
                "Yes"
            } else {
                "No"
            },
        ])
        .add_row(vec![
            String::from("Last updated"),
            option_display(
                &notification_thread
                    .updated_at
                    .as_ref()
                    .map(render_datetime_and_info),
            ),
        ]);

    println!("{table}", table = table.show());
}