yggdrasil/components/comments/
item.rs1use dioxus::prelude::*;
6
7use crate::components::comments::form::CommentForm;
8use crate::components::comments::section::CommentContext;
9use crate::models::comment::PublicComment;
10
11#[component]
21pub fn CommentItem(comment: PublicComment, post_id: i32) -> Element {
22 let ctx: CommentContext = use_context();
23 let mut active_reply = ctx.active_reply;
24
25 let depth = if comment.parent_id.is_none() && comment.depth > 0 {
27 0
28 } else {
29 comment.depth
30 };
31
32 let indent = depth.min(6) * 24;
33
34 let is_replying = active_reply() == Some(comment.id);
35 let show_reply = depth < 20;
36
37 let author_element = match &comment.author_url {
39 Some(url) if !url.is_empty() => rsx! {
40 a {
41 href: "{url}",
42 rel: "nofollow noopener",
43 target: "_blank",
44 class: "font-medium text-paper-primary hover:text-paper-accent transition-colors",
45 "{comment.author_name}"
46 }
47 },
48 _ => rsx! {
49 span { class: "font-medium text-paper-primary", "{comment.author_name}" }
50 },
51 };
52
53 rsx! {
54 div { class: "py-4", style: "margin-left: {indent}px",
55
56 div { class: "flex gap-3",
57 img {
58 src: "{comment.avatar_url}",
59 alt: "{comment.author_name} 的头像",
60 loading: "lazy",
61 decoding: "async",
62 class: "w-8 h-8 rounded-full shrink-0 mt-0.5 bg-gray-200 dark:bg-gray-800",
63 }
64
65 div { class: "flex-1 min-w-0",
66 div { class: "flex items-center gap-1.5 text-sm mb-1.5 flex-wrap",
67 {author_element}
68 span { class: "text-paper-tertiary", "·" }
69 span {
70 class: "text-paper-tertiary",
71 title: "{comment.created_at_iso}",
72 "{comment.created_at}"
73 }
74 }
75
76 div {
77 class: "prose prose-sm dark:prose-invert max-w-none text-paper-secondary md-content",
78 dangerous_inner_html: comment.content_html.as_deref().unwrap_or(""),
79 }
80
81 div { class: "flex items-center gap-3 mt-2",
82 if show_reply {
83 button {
84 class: "text-xs text-paper-tertiary hover:text-paper-accent transition-colors cursor-pointer",
85 aria_label: "回复 {comment.author_name} 的评论",
86 onclick: move |_| {
87 if is_replying {
88 active_reply.set(None);
89 } else {
90 active_reply.set(Some(comment.id));
91 }
92 },
93 if is_replying {
94 "取消回复"
95 } else {
96 "回复"
97 }
98 }
99 }
100
101 }
102
103 if is_replying {
104 CommentForm {
105 post_id,
106 parent_id: Some(comment.id),
107 parent_indent: Some(indent),
108 }
109 }
110 }
111 }
112 }
113 }
114}