Radish alpha
r
rad:z39mP9rQAaGmERfUMPULfPUi473tY
Radicle terminal user interface
Radicle
Git
lib: Switch to latest heartwood commit
Merged did:key:z6MkswQE...2C1V opened 2 years ago
4 files changed +91 -40 b03b4cfe b03b4cfe
modified Cargo.lock
@@ -1473,7 +1473,7 @@ dependencies = [
[[package]]
name = "radicle"
version = "0.2.0"
-
source = "git+https://github.com/radicle-dev/heartwood#09f2befa58dc6057e052904b6947bdd17d3b0553"
+
source = "git+https://seed.radicle.xyz/z3gqcJUoA1n9HaHKufZs5FCSGazv5#54aacc96197a48b79fcc260f94312d824f5e0a34"
dependencies = [
 "amplify",
 "base64 0.21.7",
@@ -1503,7 +1503,7 @@ dependencies = [
[[package]]
name = "radicle-cob"
version = "0.2.0"
-
source = "git+https://github.com/radicle-dev/heartwood#09f2befa58dc6057e052904b6947bdd17d3b0553"
+
source = "git+https://seed.radicle.xyz/z3gqcJUoA1n9HaHKufZs5FCSGazv5#54aacc96197a48b79fcc260f94312d824f5e0a34"
dependencies = [
 "fastrand",
 "git2",
@@ -1521,7 +1521,7 @@ dependencies = [
[[package]]
name = "radicle-crypto"
version = "0.2.0"
-
source = "git+https://github.com/radicle-dev/heartwood#09f2befa58dc6057e052904b6947bdd17d3b0553"
+
source = "git+https://seed.radicle.xyz/z3gqcJUoA1n9HaHKufZs5FCSGazv5#54aacc96197a48b79fcc260f94312d824f5e0a34"
dependencies = [
 "amplify",
 "cyphernet",
@@ -1539,7 +1539,7 @@ dependencies = [
[[package]]
name = "radicle-dag"
version = "0.2.0"
-
source = "git+https://github.com/radicle-dev/heartwood#09f2befa58dc6057e052904b6947bdd17d3b0553"
+
source = "git+https://seed.radicle.xyz/z3gqcJUoA1n9HaHKufZs5FCSGazv5#54aacc96197a48b79fcc260f94312d824f5e0a34"
dependencies = [
 "fastrand",
]
@@ -1561,7 +1561,7 @@ dependencies = [
[[package]]
name = "radicle-ssh"
version = "0.2.0"
-
source = "git+https://github.com/radicle-dev/heartwood#09f2befa58dc6057e052904b6947bdd17d3b0553"
+
source = "git+https://seed.radicle.xyz/z3gqcJUoA1n9HaHKufZs5FCSGazv5#54aacc96197a48b79fcc260f94312d824f5e0a34"
dependencies = [
 "byteorder",
 "log",
@@ -1596,7 +1596,7 @@ dependencies = [
[[package]]
name = "radicle-term"
version = "0.1.0"
-
source = "git+https://github.com/radicle-dev/heartwood#09f2befa58dc6057e052904b6947bdd17d3b0553"
+
source = "git+https://seed.radicle.xyz/z3gqcJUoA1n9HaHKufZs5FCSGazv5#54aacc96197a48b79fcc260f94312d824f5e0a34"
dependencies = [
 "anstyle-query",
 "anyhow",
modified Cargo.toml
@@ -21,8 +21,8 @@ inquire = { version = "0.6.2", default-features = false, features = ["termion",
lexopt = { version = "0.3.0" }
libc = { version = "^0.2" }
log = { version = "0.4.19" }
-
radicle = { git = "https://github.com/radicle-dev/heartwood" }
-
radicle-term = { git = "https://github.com/radicle-dev/heartwood", package = "radicle-term" }
+
radicle = { git = "https://seed.radicle.xyz/z3gqcJUoA1n9HaHKufZs5FCSGazv5" }
+
radicle-term = { git = "https://seed.radicle.xyz/z3gqcJUoA1n9HaHKufZs5FCSGazv5", package = "radicle-term" }
radicle-surf = { version = "0.18.0" }
ratatui = { git = "https://github.com/erak/ratatui", default-features = false, features = ["all-widgets", "termion"] }
simple-logging = { version = "2.0.2" }
modified bin/commands/inbox/flux/select.rs
@@ -75,8 +75,9 @@ impl TryFrom<&Context> for InboxState {

                    let items = inbox::all(&repo, &context.profile)?
                        .iter()
-
                        .map(|notif| NotificationItem::try_from((&context.profile, &repo, notif)))
+
                        .map(|notif| NotificationItem::new(&context.profile, &repo, notif))
                        .filter_map(|item| item.ok())
+
                        .flatten()
                        .collect::<Vec<_>>();

                    notifs.extend(items);
@@ -90,9 +91,10 @@ impl TryFrom<&Context> for InboxState {
                notifs
                    .iter()
                    .map(|notif| {
-
                        NotificationItem::try_from((&context.profile, &context.repository, notif))
+
                        NotificationItem::new(&context.profile, &context.repository, notif)
                    })
                    .filter_map(|item| item.ok())
+
                    .flatten()
                    .collect::<Vec<_>>()
            }
            RepositoryMode::ByRepo((rid, _)) => {
@@ -101,8 +103,9 @@ impl TryFrom<&Context> for InboxState {

                notifs
                    .iter()
-
                    .map(|notif| NotificationItem::try_from((&context.profile, &repo, notif)))
+
                    .map(|notif| NotificationItem::new(&context.profile, &repo, notif))
                    .filter_map(|item| item.ok())
+
                    .flatten()
                    .collect::<Vec<_>>()
            }
        };
modified src/flux/ui/cob.rs
@@ -1,12 +1,12 @@
use radicle::crypto::PublicKey;
use radicle::git::Oid;
-
use radicle::identity::Did;
+
use radicle::identity::{Did, Identity};
use radicle::node::{Alias, NodeId};
use radicle::{issue, patch, Profile};
use ratatui::style::{Color, Style, Stylize};
use ratatui::widgets::Cell;

-
use radicle::cob::{self, Label, ObjectId, Timestamp};
+
use radicle::cob::{Label, ObjectId, Timestamp, TypedId};
use radicle::issue::{Issue, IssueId, Issues};
use radicle::node::notifications::{Notification, NotificationId, NotificationKind};
use radicle::node::AliasStore;
@@ -51,13 +51,16 @@ pub enum NotificationKindItem {
        status: String,
        id: Option<ObjectId>,
    },
+
    Unknown {
+
        refname: String,
+
    },
}

-
impl TryFrom<(&Repository, &Notification)> for NotificationKindItem {
-
    type Error = anyhow::Error;
-

-
    fn try_from(value: (&Repository, &Notification)) -> Result<Self, Self::Error> {
-
        let (repo, notification) = value;
+
impl NotificationKindItem {
+
    pub fn new(
+
        repo: &Repository,
+
        notification: &Notification,
+
    ) -> Result<Option<Self>, anyhow::Error> {
        // TODO: move out of here
        let issues = Issues::open(repo)?;
        let patches = Patches::open(repo)?;
@@ -87,45 +90,69 @@ impl TryFrom<(&Repository, &Notification)> for NotificationKindItem {
                }
                .to_owned();

-
                Ok(NotificationKindItem::Branch {
+
                Ok(Some(NotificationKindItem::Branch {
                    name: name.to_string(),
                    summary: message,
                    status: status.to_string(),
                    id: head.map(ObjectId::from),
-
                })
+
                }))
            }
-
            NotificationKind::Cob { type_name, id } => {
-
                let (category, summary, status) = if *type_name == *cob::issue::TYPENAME {
+
            NotificationKind::Cob { typed_id } => {
+
                let TypedId { id, .. } = typed_id;
+
                let (category, summary, state) = if typed_id.is_issue() {
                    let Some(issue) = issues.get(id)? else {
                        // Issue could have been deleted after notification was created.
-
                        anyhow::bail!("Issue deleted after notification was created");
+
                        return Ok(None);
                    };
                    (
                        String::from("issue"),
                        issue.title().to_owned(),
                        issue.state().to_string(),
                    )
-
                } else if *type_name == *cob::patch::TYPENAME {
+
                } else if typed_id.is_patch() {
                    let Some(patch) = patches.get(id)? else {
                        // Patch could have been deleted after notification was created.
-
                        anyhow::bail!("patch deleted after notification was created");
+
                        return Ok(None);
                    };
                    (
                        String::from("patch"),
                        patch.title().to_owned(),
                        patch.state().to_string(),
                    )
+
                } else if typed_id.is_identity() {
+
                    let Ok(identity) = Identity::get(id, repo) else {
+
                        log::error!(
+
                            target: "cli",
+
                            "Error retrieving identity {id} for notification {}", notification.id
+
                        );
+
                        return Ok(None);
+
                    };
+
                    let Some(rev) = notification
+
                        .update
+
                        .new()
+
                        .and_then(|id| identity.revision(&id))
+
                    else {
+
                        log::error!(
+
                            target: "cli",
+
                            "Error retrieving identity revision for notification {}", notification.id
+
                        );
+
                        return Ok(None);
+
                    };
+
                    (String::from("id"), rev.title.clone(), rev.state.to_string())
                } else {
-
                    (type_name.to_string(), "".to_owned(), String::new())
+
                    (typed_id.type_name.to_string(), "".to_owned(), String::new())
                };

-
                Ok(NotificationKindItem::Cob {
+
                Ok(Some(NotificationKindItem::Cob {
                    type_name: category.to_string(),
                    summary: summary.to_string(),
-
                    status: status.to_string(),
+
                    status: state.to_string(),
                    id: Some(*id),
-
                })
+
                }))
            }
+
            NotificationKind::Unknown { refname } => Ok(Some(NotificationKindItem::Unknown {
+
                refname: refname.to_string(),
+
            })),
        }
    }
}
@@ -146,27 +173,32 @@ pub struct NotificationItem {
    pub timestamp: Timestamp,
}

-
impl TryFrom<(&Profile, &Repository, &Notification)> for NotificationItem {
-
    type Error = anyhow::Error;
-

-
    fn try_from(value: (&Profile, &Repository, &Notification)) -> Result<Self, Self::Error> {
-
        let (profile, repo, notification) = value;
+
impl NotificationItem {
+
    pub fn new(
+
        profile: &Profile,
+
        repo: &Repository,
+
        notification: &Notification,
+
    ) -> Result<Option<Self>, anyhow::Error> {
        let project = profile
            .storage
            .repository(repo.id)?
            .identity_doc()?
            .project()?;
        let name = project.name().to_string();
-
        let kind = NotificationKindItem::try_from((repo, notification))?;
+
        let kind = NotificationKindItem::new(repo, notification)?;

-
        Ok(NotificationItem {
+
        if kind.is_none() {
+
            return Ok(None);
+
        }
+

+
        Ok(Some(NotificationItem {
            id: notification.id,
            project: name,
            seen: notification.status.is_read(),
-
            kind,
+
            kind: kind.unwrap(),
            author: AuthorItem::new(notification.remote, profile),
            timestamp: notification.timestamp.into(),
-
        })
+
        }))
    }
}

@@ -178,7 +210,12 @@ impl ToRow<8> for NotificationItem {
                summary,
                status,
                id: _,
-
            } => ("branch".to_string(), summary, status, name.to_string()),
+
            } => (
+
                "branch".to_string(),
+
                summary.clone(),
+
                status.clone(),
+
                name.to_string(),
+
            ),
            NotificationKindItem::Cob {
                type_name,
                summary,
@@ -186,8 +223,19 @@ impl ToRow<8> for NotificationItem {
                id,
            } => {
                let id = id.map(|id| format::cob(&id)).unwrap_or_default();
-
                (type_name.to_string(), summary, status, id.to_string())
+
                (
+
                    type_name.to_string(),
+
                    summary.clone(),
+
                    status.clone(),
+
                    id.to_string(),
+
                )
            }
+
            NotificationKindItem::Unknown { refname } => (
+
                refname.to_string(),
+
                String::new(),
+
                String::new(),
+
                String::new(),
+
            ),
        };

        let id = span::notification_id(format!(" {:-03}", &self.id));