update member row

This commit is contained in:
2026-10-01 10:18:36 +07:00
parent 75b0f49d9e
commit a93be19e81
6 changed files with 103 additions and 263 deletions
+53 -33
View File
@@ -8,10 +8,10 @@ use chat::{ChatEvent, ChatRegistry, Room, RoomKind};
use common::TimestampExt;
use gpui::prelude::FluentBuilder;
use gpui::{
AnyElement, App, AppContext, Context, Div, Entity, EventEmitter, FocusHandle, Focusable,
InteractiveElement, IntoElement, ObjectFit, ParentElement, Render, SharedString, Stateful,
Styled, StyledImage, Subscription, Task, UniformListScrollHandle, WeakEntity, Window, div, img,
px, relative, retain_all, uniform_list,
AnyElement, App, AppContext, ClipboardItem, Context, Div, Entity, EventEmitter, FocusHandle,
Focusable, InteractiveElement, IntoElement, ObjectFit, ParentElement, Render, SharedString,
Stateful, Styled, StyledImage, Subscription, Task, UniformListScrollHandle, WeakEntity, Window,
div, img, px, relative, retain_all, uniform_list,
};
use nip29::{Group, GroupKey, GroupsEvent, GroupsRegistry, Membership};
use nostr_sdk::prelude::*;
@@ -922,10 +922,14 @@ impl Sidebar {
}
fn render_group(&mut self, group: Entity<Group>, cx: &mut Context<Self>) -> AnyElement {
let (banner, name, seed, picture, total_members, rows) = {
let admin = NostrRegistry::global(cx)
.read(cx)
.current_user()
.is_some_and(|me| group.read(cx).admins().contains(&me));
let (name, seed, picture, total_members, rows) = {
let group = group.read(cx);
let admins = group.admins();
let metadata = group.metadata();
let mut admin_rows = Vec::new();
let mut member_rows = Vec::new();
@@ -965,9 +969,6 @@ impl Sidebar {
}
(
metadata.and_then(|metadata| {
metadata.banner.clone().or_else(|| metadata.picture.clone())
}),
group.display_name(),
group.key().cache_tag(),
group.display_image(),
@@ -977,30 +978,13 @@ impl Sidebar {
};
let rows = Rc::new(rows);
let member_group = group.downgrade();
v_flex()
.flex_1()
.min_h_0()
.w_full()
.gap_2()
.when_some(banner, |this, banner| {
this.child(
div().px_2().flex_shrink_0().child(
div()
.h_40()
.w_full()
.relative()
.overflow_hidden()
.rounded(cx.theme().radius_lg)
.child(
img(banner)
.size_full()
.rounded(cx.theme().radius_lg)
.object_fit(ObjectFit::Fill),
),
),
)
})
.child(
h_flex()
.px_2()
@@ -1008,7 +992,8 @@ impl Sidebar {
.justify_between()
.child(
h_flex()
.gap_2()
.pl_0p5()
.gap_1()
.flex_shrink_1()
.child(Avatar::from_source(picture).seed(seed).small())
.child(
@@ -1046,7 +1031,13 @@ impl Sidebar {
"group-rows",
rows.len(),
cx.processor(move |this, range, _window, cx| {
this.render_group_rows(range, rows.as_slice(), cx)
this.render_group_rows(
range,
rows.as_slice(),
&member_group,
admin,
cx,
)
}),
)
.track_scroll(&self.group_scroll)
@@ -1062,6 +1053,8 @@ impl Sidebar {
&self,
range: Range<usize>,
rows: &[GroupRow],
group: &WeakEntity<Group>,
admin: bool,
cx: &mut Context<Self>,
) -> Vec<AnyElement> {
rows.get(range)
@@ -1069,7 +1062,9 @@ impl Sidebar {
.flatten()
.map(|row| match row {
GroupRow::Section(section) => self.section_row(*section, cx),
GroupRow::Member { public_key, roles } => self.member_row(public_key, roles, cx),
GroupRow::Member { public_key, roles } => {
self.member_row(public_key, roles, group, admin, cx)
}
})
.collect()
}
@@ -1106,16 +1101,22 @@ impl Sidebar {
&self,
public_key: &PublicKey,
roles: &[String],
group: &WeakEntity<Group>,
admin: bool,
cx: &mut Context<Self>,
) -> AnyElement {
let hide_avatar = AppSettings::get_hide_avatar(cx);
let persons = PersonRegistry::global(cx);
let person = persons.read(cx).get(public_key, cx);
let public_key = *public_key;
let group = group.clone();
Nav::new(public_key.to_hex())
.label(person.name())
.text_sm()
.font_medium()
.clickable(true)
.when(!hide_avatar, |this| {
this.prefix(
Avatar::new(person.avatar())
@@ -1133,10 +1134,29 @@ impl Sidebar {
.child(SharedString::from(roles.join(", "))),
)
})
.on_click({
let public_key = *public_key;
.dropdown_menu(move |menu, _window, _cx| {
let menu = menu
.item(
PopupMenuItem::new("View profile").on_click(move |_, window, cx| {
profile::open(public_key, window, cx);
}),
)
.item(PopupMenuItem::new("Copy").on_click(move |_, _, cx| {
let npub = public_key.to_bech32().unwrap_or_default();
cx.write_to_clipboard(ClipboardItem::new_string(npub));
}));
move |_event, window, cx| profile::open(public_key, window, cx)
if !admin {
return menu;
}
menu.separator()
.item(PopupMenuItem::new("Remove").on_click({
let group = group.clone();
move |_event, window, cx| {
nip29_ui::remove_member(group.clone(), public_key, window, cx);
}
}))
})
.into_any_element()
}