Radish alpha
r
rad:z4D5UCArafTzTQpDZNQRuqswh3ury
Radicle desktop app
Radicle
Git
Add tauri commands to create comments and reply
Merged did:key:z6MkkfM3...sVz5 opened 1 year ago
10 files changed +231 -1 8731506b 9334ffb3
added src-tauri/bindings/CobOptions.ts
@@ -0,0 +1,3 @@
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
+

+
export type CobOptions = { announce?: boolean };
added src-tauri/bindings/CodeLocation.ts
@@ -0,0 +1,9 @@
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
+
import type { CodeRange } from "./CodeRange";
+

+
export type CodeLocation = {
+
  commit: string;
+
  path: string;
+
  old: CodeRange | null;
+
  new: CodeRange | null;
+
};
added src-tauri/bindings/CodeRange.ts
@@ -0,0 +1,5 @@
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
+

+
export type CodeRange =
+
  | { type: "lines"; range: { start: number; end: number } }
+
  | { type: "chars"; line: number; range: { start: number; end: number } };
added src-tauri/bindings/NewIssueComment.ts
@@ -0,0 +1,8 @@
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
+

+
export type NewIssueComment = {
+
  id: string;
+
  body: string;
+
  replyTo?: string;
+
  embeds: { name: string; content: string }[];
+
};
added src-tauri/bindings/NewPatchComment.ts
@@ -0,0 +1,11 @@
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
+
import type { CodeLocation } from "./CodeLocation";
+

+
export type NewPatchComment = {
+
  id: string;
+
  revision: string;
+
  body: string;
+
  replyTo?: string;
+
  location: CodeLocation | null;
+
  embeds: { name: string; content: string }[];
+
};
modified src-tauri/src/commands.rs
@@ -2,3 +2,4 @@ pub mod auth;
pub mod cobs;
pub mod profile;
pub mod repos;
+
pub mod thread;
added src-tauri/src/commands/thread.rs
@@ -0,0 +1,68 @@
+
use std::str::FromStr;
+

+
use radicle::cob::{EntryId, ObjectId};
+
use radicle::git::Oid;
+
use radicle::identity::RepoId;
+
use radicle::node::Handle;
+
use radicle::storage::ReadStorage;
+
use radicle::Node;
+

+
use crate::error::Error;
+
use crate::types::cobs::{CobOptions, NewIssueComment, NewPatchComment};
+
use crate::AppState;
+

+
#[tauri::command]
+
pub fn create_issue_comment(
+
    ctx: tauri::State<AppState>,
+
    rid: RepoId,
+
    new: NewIssueComment,
+
    opts: CobOptions,
+
) -> Result<Oid, Error> {
+
    let mut node = Node::new(ctx.profile.socket());
+
    let signer = ctx.profile.signer()?;
+
    let issue_id = ObjectId::from_str(&new.id)?;
+
    let repo = ctx.profile.storage.repository(rid)?;
+
    let mut issues = ctx.profile.issues_mut(&repo)?;
+
    let mut issue = issues.get_mut(&issue_id)?;
+
    let id = new.reply_to.unwrap_or_else(|| {
+
        let (root_id, _) = issue.root();
+
        *root_id
+
    });
+
    let oid = issue.comment(new.body, id, new.embeds, &signer)?;
+

+
    if opts.announce() {
+
        node.announce_refs(rid)?;
+
    }
+

+
    Ok::<_, Error>(oid)
+
}
+

+
#[tauri::command]
+
pub fn create_patch_comment(
+
    ctx: tauri::State<AppState>,
+
    rid: RepoId,
+
    new: NewPatchComment,
+
    opts: CobOptions,
+
) -> Result<Oid, Error> {
+
    let mut node = Node::new(ctx.profile.socket());
+
    let signer = ctx.profile.signer()?;
+
    let patch_id = ObjectId::from_str(&new.id)?;
+
    let revision_id = EntryId::from_str(&new.revision)?;
+
    let repo = ctx.profile.storage.repository(rid)?;
+
    let mut patches = ctx.profile.patches_mut(&repo)?;
+
    let mut patch = patches.get_mut(&patch_id)?;
+
    let oid = patch.comment(
+
        revision_id.into(),
+
        new.body,
+
        new.reply_to,
+
        new.location.map(|l| l.into()),
+
        new.embeds,
+
        &signer,
+
    )?;
+

+
    if opts.announce() {
+
        node.announce_refs(rid)?;
+
    }
+

+
    Ok::<_, Error>(oid)
+
}
modified src-tauri/src/error.rs
@@ -54,6 +54,14 @@ pub enum Error {
    #[error(transparent)]
    Surf(#[from] radicle_surf::Error),

+
    /// Issue error.
+
    #[error(transparent)]
+
    Issue(#[from] radicle::issue::Error),
+

+
    /// Patch error.
+
    #[error(transparent)]
+
    Patch(#[from] radicle::patch::Error),
+

    /// Crypto error.
    #[error(transparent)]
    Crypto(#[from] radicle::crypto::ssh::keystore::Error),
@@ -77,6 +85,10 @@ pub enum Error {
    #[error(transparent)]
    Tauri(#[from] tauri::Error),

+
    /// Parse ObjectId error.
+
    #[error(transparent)]
+
    ParseObjectId(#[from] radicle::cob::object::ParseObjectId),
+

    /// Storage error.
    #[error(transparent)]
    Storage(#[from] radicle::storage::Error),
modified src-tauri/src/lib.rs
@@ -17,7 +17,7 @@ use radicle::storage::git::Repository;
use radicle::storage::{ReadRepository, ReadStorage};
use radicle::Node;

-
use commands::{auth, cobs, profile, repos};
+
use commands::{auth, cobs, profile, repos, thread};
use types::repo::SupportedPayloads;

struct AppState {
@@ -142,6 +142,8 @@ pub fn run() {
            repos::repo_by_id,
            cobs::list_issues,
            cobs::list_patches,
+
            thread::create_issue_comment,
+
            thread::create_patch_comment,
            profile::config,
        ])
        .run(tauri::generate_context!())
modified src-tauri/src/types/cobs.rs
@@ -1,8 +1,10 @@
use radicle::cob;
+
use radicle::git;
use radicle::identity;
use radicle::issue;
use radicle::node::{Alias, AliasStore};
use radicle::patch;
+
use serde::Deserialize;
use serde::Serialize;
use ts_rs::TS;

@@ -103,3 +105,112 @@ impl Patch {
        }
    }
}
+

+
#[derive(TS, Serialize, Deserialize)]
+
#[ts(export)]
+
#[serde(rename_all = "camelCase")]
+
pub struct NewPatchComment {
+
    pub id: String,
+
    pub revision: String,
+
    pub body: String,
+
    #[ts(as = "Option<String>")]
+
    #[ts(optional)]
+
    pub reply_to: Option<cob::thread::CommentId>,
+
    pub location: Option<CodeLocation>,
+
    #[ts(type = "{ name: string, content: string }[]")]
+
    pub embeds: Vec<cob::Embed>,
+
}
+

+
#[derive(TS, Serialize, Deserialize)]
+
#[ts(export)]
+
#[serde(rename_all = "camelCase")]
+
pub struct NewIssueComment {
+
    pub id: String,
+
    pub body: String,
+
    #[ts(as = "Option<String>")]
+
    #[ts(optional)]
+
    pub reply_to: Option<cob::thread::CommentId>,
+
    #[ts(type = "{ name: string, content: string }[]")]
+
    pub embeds: Vec<cob::Embed>,
+
}
+

+
#[derive(TS, Serialize, Deserialize)]
+
#[serde(rename_all = "camelCase")]
+
#[ts(export)]
+
pub struct CodeLocation {
+
    #[ts(as = "String")]
+
    commit: git::Oid,
+
    path: std::path::PathBuf,
+
    old: Option<CodeRange>,
+
    new: Option<CodeRange>,
+
}
+

+
impl From<cob::CodeLocation> for CodeLocation {
+
    fn from(val: cob::CodeLocation) -> Self {
+
        Self {
+
            commit: val.commit,
+
            path: val.path,
+
            old: val.old.map(|o| o.into()),
+
            new: val.new.map(|o| o.into()),
+
        }
+
    }
+
}
+

+
impl From<CodeLocation> for cob::CodeLocation {
+
    fn from(val: CodeLocation) -> Self {
+
        Self {
+
            commit: val.commit,
+
            path: val.path,
+
            old: val.old.map(|o| o.into()),
+
            new: val.new.map(|o| o.into()),
+
        }
+
    }
+
}
+

+
#[derive(TS, Serialize, Deserialize)]
+
#[serde(rename_all = "camelCase", tag = "type")]
+
#[ts(export)]
+
pub enum CodeRange {
+
    Lines {
+
        #[ts(type = "{ start: number, end: number }")]
+
        range: std::ops::Range<usize>,
+
    },
+
    Chars {
+
        line: usize,
+
        #[ts(type = "{ start: number, end: number }")]
+
        range: std::ops::Range<usize>,
+
    },
+
}
+

+
impl From<cob::CodeRange> for CodeRange {
+
    fn from(val: cob::CodeRange) -> Self {
+
        match val {
+
            cob::CodeRange::Chars { line, range } => Self::Chars { line, range },
+
            cob::CodeRange::Lines { range } => Self::Lines { range },
+
        }
+
    }
+
}
+

+
impl From<CodeRange> for cob::CodeRange {
+
    fn from(val: CodeRange) -> Self {
+
        match val {
+
            CodeRange::Chars { line, range } => Self::Chars { line, range },
+
            CodeRange::Lines { range } => Self::Lines { range },
+
        }
+
    }
+
}
+

+
#[derive(TS, Serialize, Deserialize)]
+
#[serde(rename_all = "camelCase")]
+
#[ts(export)]
+
pub struct CobOptions {
+
    #[ts(as = "Option<bool>")]
+
    #[ts(optional)]
+
    announce: Option<bool>,
+
}
+

+
impl CobOptions {
+
    pub fn announce(&self) -> bool {
+
        self.announce.unwrap_or(true)
+
    }
+
}