Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cob: Move comment reactions to comment
Alexis Sellier committed 2 years ago
commit e4ab523669d6f90537665a2a4ee0ed05f5a05d34
parent 8b010c27a2a92d360bd5e4da3b8d2298ca9886cc
3 files changed +25 -34
modified radicle-httpd/src/api/json.rs
@@ -11,7 +11,7 @@ use radicle::cob::patch::Merge;
use radicle::cob::patch::Review;
use radicle::cob::patch::{Patch, PatchId};
use radicle::cob::thread;
-
use radicle::cob::thread::{CommentId, Thread};
+
use radicle::cob::thread::CommentId;
use radicle::cob::{ActorId, Author, Reaction, Timestamp};
use radicle::git::RefString;
use radicle::node::AliasStore;
@@ -105,7 +105,7 @@ pub(crate) fn issue(id: IssueId, issue: Issue, aliases: &impl AliasStore) -> Val
        "assignees": issue.assigned().collect::<Vec<_>>(),
        "discussion": issue
          .comments()
-
          .map(|(id, comment)| Comment::new(id, comment, issue.thread(), aliases))
+
          .map(|(id, comment)| Comment::new(id, comment, aliases))
          .collect::<Vec<_>>(),
        "tags": issue.tags().collect::<Vec<_>>(),
    })
@@ -136,7 +136,7 @@ pub(crate) fn patch(
                "oid": rev.head(),
                "refs": get_refs(repo, patch.author().id(), &rev.head()).unwrap_or(vec![]),
                "discussions": rev.discussion().comments()
-
                  .map(|(id, comment)| Comment::new(id, comment, rev.discussion(), aliases))
+
                  .map(|(id, comment)| Comment::new(id, comment,  aliases))
                  .collect::<Vec<_>>(),
                "timestamp": rev.timestamp(),
                "reviews": rev.reviews().map(|(nid, _review)| review(nid, aliases.alias(nid), _review)).collect::<Vec<_>>(),
@@ -245,18 +245,13 @@ struct Comment<'a> {
}

impl<'a> Comment<'a> {
-
    fn new(
-
        id: &'a CommentId,
-
        comment: &'a thread::Comment,
-
        thread: &'a Thread,
-
        aliases: &impl AliasStore,
-
    ) -> Self {
+
    fn new(id: &'a CommentId, comment: &'a thread::Comment, aliases: &impl AliasStore) -> Self {
        let comment_author = Author::new(comment.author());
        Self {
            id: *id,
            author: author(&comment_author, aliases.alias(comment_author.id())),
            body: comment.body(),
-
            reactions: thread.reactions(id).collect::<Vec<_>>(),
+
            reactions: comment.reactions().collect::<Vec<_>>(),
            timestamp: comment.timestamp(),
            reply_to: comment.reply_to(),
        }
modified radicle/src/cob/issue.rs
@@ -836,7 +836,7 @@ mod test {

        let id = issue.id;
        let issue = issues.get(&id).unwrap().unwrap();
-
        let (_, r) = issue.reactions(&comment).next().unwrap();
+
        let (_, r) = issue.comment(&comment).unwrap().reactions().next().unwrap();

        assert_eq!(r, &reaction);

modified radicle/src/cob/thread.rs
@@ -61,6 +61,8 @@ pub struct Comment {
    author: ActorId,
    /// The comment body.
    edits: GMap<Lamport, Max<Edit>>,
+
    /// Reactions to this comment.
+
    reactions: LWWSet<(ActorId, Reaction)>,
    /// Comment this is a reply to.
    /// Should always be set, except for the root comment.
    reply_to: Option<CommentId>,
@@ -78,6 +80,7 @@ impl Comment {

        Self {
            author,
+
            reactions: LWWSet::default(),
            edits: GMap::singleton(Lamport::initial(), Max::from(edit)),
            reply_to,
        }
@@ -124,6 +127,11 @@ impl Comment {
    pub fn edit(&mut self, clock: Lamport, body: String, timestamp: Timestamp) {
        self.edits.insert(clock, Edit { body, timestamp }.into())
    }
+

+
    /// Comment reactions.
+
    pub fn reactions(&self) -> impl Iterator<Item = (&ActorId, &Reaction)> {
+
        self.reactions.iter().map(|(a, r)| (a, r))
+
    }
}

impl PartialOrd for Comment {
@@ -175,16 +183,13 @@ impl From<Action> for nonempty::NonEmpty<Action> {
pub struct Thread {
    /// The comments under the thread.
    comments: GMap<CommentId, Redactable<Comment>>,
-
    /// Reactions to changes.
-
    reactions: GMap<CommentId, LWWSet<(ActorId, Reaction), Lamport>>,
    /// Comment timeline.
-
    timeline: GSet<(Lamport, EntryId)>,
+
    timeline: GSet<(Lamport, CommentId)>,
}

impl Semilattice for Thread {
    fn merge(&mut self, other: Self) {
        self.comments.merge(other.comments);
-
        self.reactions.merge(other.reactions);
        self.timeline.merge(other.timeline);
    }
}
@@ -193,7 +198,6 @@ impl Thread {
    pub fn new(id: CommentId, comment: Comment) -> Self {
        Self {
            comments: GMap::singleton(id, Redactable::Present(comment)),
-
            reactions: GMap::default(),
            timeline: GSet::default(),
        }
    }
@@ -244,17 +248,6 @@ impl Thread {
        })
    }

-
    pub fn reactions<'a>(
-
        &'a self,
-
        to: &'a CommentId,
-
    ) -> impl Iterator<Item = (&ActorId, &Reaction)> {
-
        self.reactions
-
            .get(to)
-
            .into_iter()
-
            .flat_map(move |rs| rs.iter())
-
            .map(|(a, r)| (a, r))
-
    }
-

    pub fn comments(&self) -> impl DoubleEndedIterator<Item = (&CommentId, &Comment)> + '_ {
        self.timeline.iter().filter_map(|(_, id)| {
            self.comments
@@ -335,14 +328,17 @@ impl cob::store::FromHistory for Thread {
                    active,
                } => {
                    let key = (op.author, reaction);
-
                    let reactions = if active {
-
                        LWWSet::singleton(key, op.clock)
+
                    if let Some(redactable) = self.comments.get_mut(&to) {
+
                        if let Redactable::Present(comment) = redactable {
+
                            if active {
+
                                comment.reactions.insert(key, op.clock);
+
                            } else {
+
                                comment.reactions.remove(key, op.clock);
+
                            }
+
                        }
                    } else {
-
                        let mut set = LWWSet::default();
-
                        set.remove(key, op.clock);
-
                        set
-
                    };
-
                    self.reactions.insert(to, reactions);
+
                        return Err(Error::Missing(id));
+
                    }
                }
            }
        }