diff --git a/src/components/comments/list.rs b/src/components/comments/list.rs index 6b5d7ac..ac6cd3a 100644 --- a/src/components/comments/list.rs +++ b/src/components/comments/list.rs @@ -5,34 +5,76 @@ use crate::hooks::comment_storage::PendingComment; use crate::components::comments::item::CommentItem; use crate::components::comments::pending_item::PendingCommentItem; +#[derive(Clone)] enum MergedComment { Approved(PublicComment), Pending(PendingComment), } -fn merge_comments( +fn merge_and_treeify( approved: Vec, pending: Vec, ) -> Vec { - let mut merged: Vec = approved + use std::collections::{HashMap, HashSet}; + + let all: Vec = approved .into_iter() .map(MergedComment::Approved) .chain(pending.into_iter().map(MergedComment::Pending)) .collect(); - merged.sort_by(|a, b| { - let time_a = match a { - MergedComment::Approved(c) => c.created_at_iso.as_str(), - MergedComment::Pending(c) => c.created_at.as_str(), - }; - let time_b = match b { - MergedComment::Approved(c) => c.created_at_iso.as_str(), - MergedComment::Pending(c) => c.created_at.as_str(), - }; - time_a.cmp(time_b) - }); + let all_ids: HashSet = all.iter().map(|c| match c { + MergedComment::Approved(c) => c.id, + MergedComment::Pending(c) => c.id, + }).collect(); - merged + let mut children_map: HashMap, Vec> = HashMap::new(); + for comment in all { + let parent_id = match &comment { + MergedComment::Approved(c) => c.parent_id, + MergedComment::Pending(c) => c.parent_id, + }; + let effective_parent = match parent_id { + Some(pid) if !all_ids.contains(&pid) => None, + _ => parent_id, + }; + children_map.entry(effective_parent).or_default().push(comment); + } + + for children in children_map.values_mut() { + children.sort_by(|a, b| { + let time_a = match a { + MergedComment::Approved(c) => c.created_at_iso.as_str(), + MergedComment::Pending(c) => c.created_at.as_str(), + }; + let time_b = match b { + MergedComment::Approved(c) => c.created_at_iso.as_str(), + MergedComment::Pending(c) => c.created_at.as_str(), + }; + time_a.cmp(time_b) + }); + } + + fn dfs( + parent_id: Option, + children_map: &HashMap, Vec>, + result: &mut Vec, + ) { + if let Some(children) = children_map.get(&parent_id) { + for child in children { + result.push(child.clone()); + let child_id = match child { + MergedComment::Approved(c) => Some(c.id), + MergedComment::Pending(c) => Some(c.id), + }; + dfs(child_id, children_map, result); + } + } + } + + let mut result = Vec::new(); + dfs(None, &children_map, &mut result); + result } #[component] @@ -41,7 +83,7 @@ pub fn CommentList( pending: Vec, post_id: i32, ) -> Element { - let merged = merge_comments(comments, pending); + let merged = merge_and_treeify(comments, pending); rsx! { div { class: "space-y-0 divide-y divide-gray-100 dark:divide-[#2a2a2a]",