diff --git a/assets/icons/ban.svg b/assets/icons/ban.svg
new file mode 100644
index 00000000..0129765f
--- /dev/null
+++ b/assets/icons/ban.svg
@@ -0,0 +1 @@
+
diff --git a/assets/icons/login.svg b/assets/icons/login.svg
new file mode 100644
index 00000000..dc5ec458
--- /dev/null
+++ b/assets/icons/login.svg
@@ -0,0 +1 @@
+
diff --git a/crates/nip29_ui/src/message.rs b/crates/nip29_ui/src/message.rs
index 142a8eca..7bb3b0b2 100644
--- a/crates/nip29_ui/src/message.rs
+++ b/crates/nip29_ui/src/message.rs
@@ -13,6 +13,7 @@ use theme::ActiveTheme;
use ui::avatar::Avatar;
use ui::menu::{ContextMenu, PopupMenu, PopupMenuItem};
use ui::message::MessageRow;
+use ui::{Icon, IconName, Sizable, StyledExt, h_flex};
use crate::GroupPanel;
@@ -134,20 +135,63 @@ pub(crate) fn render_activity(ix: usize, activity: &Activity, cx: &App) -> AnyEl
let subject = persons.read(cx).get(&activity.subject(), cx);
let hide_avatar = AppSettings::get_hide_avatar(cx);
- MessageRow::new(ix)
- .show_author(true)
- .hide_avatar(hide_avatar)
- .avatar(
- Avatar::new(subject.avatar())
- .seed(subject.avatar_seed())
- .flex_shrink_0(),
+ h_flex()
+ .id(ix)
+ .w_full()
+ .gap_2()
+ .py_1()
+ .px_3()
+ .hover(|this| this.bg(cx.theme().surface_background))
+ .child(badge(activity, cx))
+ .when(!hide_avatar, |this| {
+ this.child(
+ Avatar::new(subject.avatar())
+ .seed(subject.avatar_seed())
+ .small()
+ .flex_shrink_0(),
+ )
+ })
+ .child(
+ div()
+ .min_w_0()
+ .truncate()
+ .text_sm()
+ .font_semibold()
+ .child(subject.name()),
)
- .author(SharedString::from(format!(
- "{} {}",
- subject.name(),
- action(activity)
- )))
- .timestamp(activity.created_at.to_human_time())
+ .child(
+ div()
+ .min_w_0()
+ .truncate()
+ .text_sm()
+ .text_color(cx.theme().text_placeholder)
+ .child(SharedString::from(action(activity))),
+ )
+ .child(
+ div()
+ .flex_shrink_0()
+ .ml_1()
+ .text_xs()
+ .text_color(cx.theme().text_placeholder)
+ .child(activity.created_at.to_ago()),
+ )
+ .into_any_element()
+}
+
+fn badge(activity: &Activity, cx: &App) -> AnyElement {
+ let (icon, color) = match activity.kind {
+ Kind::GroupJoinRequest => (IconName::Login, cx.theme().icon_accent),
+ Kind::GroupPutUser => (IconName::Login, cx.theme().icon_accent),
+ Kind::GroupLeaveRequest => (IconName::Logout, cx.theme().text_danger),
+ Kind::GroupRemoveUser => (IconName::Ban, cx.theme().text_danger),
+ _ => (IconName::Info, cx.theme().icon_muted),
+ };
+
+ h_flex()
+ .flex_shrink_0()
+ .justify_center()
+ .size_8()
+ .child(Icon::new(icon).small().text_color(color))
.into_any_element()
}
diff --git a/crates/ui/src/icon.rs b/crates/ui/src/icon.rs
index 1e708c06..198f5977 100644
--- a/crates/ui/src/icon.rs
+++ b/crates/ui/src/icon.rs
@@ -25,6 +25,7 @@ pub enum IconName {
ArrowDownCircle,
Boom,
Book,
+ Ban,
ChevronDown,
CaretDown,
CaretRight,
@@ -50,6 +51,7 @@ pub enum IconName {
Link,
Loader,
Lock,
+ Login,
Logout,
Message,
Moon,
@@ -106,6 +108,7 @@ impl IconNamed for IconName {
Self::ArrowDownCircle => "icons/arrow-down-circle.svg",
Self::Boom => "icons/boom.svg",
Self::Book => "icons/book.svg",
+ Self::Ban => "icons/ban.svg",
Self::ChevronDown => "icons/chevron-down.svg",
Self::CaretDown => "icons/caret-down.svg",
Self::CaretRight => "icons/caret-right.svg",
@@ -131,6 +134,7 @@ impl IconNamed for IconName {
Self::Link => "icons/link.svg",
Self::Loader => "icons/loader.svg",
Self::Lock => "icons/lock.svg",
+ Self::Login => "icons/login.svg",
Self::Logout => "icons/logout.svg",
Self::Message => "icons/message.svg",
Self::Moon => "icons/moon.svg",