From 128f7a12425650a93d4e67467858498a30b3c9af Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Mon, 30 Mar 2026 11:57:12 +0700 Subject: [PATCH] . --- crates/chat/src/lib.rs | 5 +++ crates/coop/src/panels/trash.rs | 77 +++++++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 9 deletions(-) diff --git a/crates/chat/src/lib.rs b/crates/chat/src/lib.rs index bdc4994..abbfdf2 100644 --- a/crates/chat/src/lib.rs +++ b/crates/chat/src/lib.rs @@ -450,6 +450,11 @@ impl ChatRegistry { self.trashes.read(cx).len() } + /// Get the trash messages entity. + pub fn trashes(&self) -> Entity> { + self.trashes.clone() + } + /// Get the relays that have seen a given message. pub fn seen_on(&self, id: &EventId) -> HashSet { self.seens diff --git a/crates/coop/src/panels/trash.rs b/crates/coop/src/panels/trash.rs index f3bbb79..e4c7696 100644 --- a/crates/coop/src/panels/trash.rs +++ b/crates/coop/src/panels/trash.rs @@ -1,15 +1,13 @@ +use chat::ChatRegistry; use gpui::{ AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable, - IntoElement, ParentElement, Render, SharedString, Styled, Window, div, svg, + InteractiveElement, IntoElement, ListAlignment, ListState, ParentElement, Render, SharedString, + Styled, Window, div, list, px, }; -use state::NostrRegistry; use theme::ActiveTheme; -use ui::button::{Button, ButtonVariants}; -use ui::dock::{DockPlacement, Panel, PanelEvent}; -use ui::{Icon, IconName, Sizable, StyledExt, h_flex, v_flex}; - -use crate::panels::profile; -use crate::workspace::Workspace; +use ui::dock::{Panel, PanelEvent}; +use ui::scroll::Scrollbar; +use ui::v_flex; pub fn init(window: &mut Window, cx: &mut App) -> Entity { cx.new(|cx| TrashPanel::new(window, cx)) @@ -18,13 +16,56 @@ pub fn init(window: &mut Window, cx: &mut App) -> Entity { pub struct TrashPanel { name: SharedString, focus_handle: FocusHandle, + + /// List state for messages + list_state: ListState, } impl TrashPanel { fn new(_window: &mut Window, cx: &mut App) -> Self { + let chat = ChatRegistry::global(cx); + let count = chat.read(cx).count_trash_messages(cx); + let list_state = ListState::new(count, ListAlignment::Bottom, px(1024.)); + Self { name: "Trash".into(), focus_handle: cx.focus_handle(), + list_state, + } + } + + fn render_list_item( + &mut self, + ix: usize, + _window: &mut Window, + cx: &mut Context, + ) -> AnyElement { + let chat = ChatRegistry::global(cx); + let trashes = chat.read(cx).trashes(); + + if let Some(message) = trashes.read(cx).iter().nth(ix) { + v_flex() + .id(ix) + .p_2() + .rounded(cx.theme().radius) + .bg(cx.theme().elevated_surface_background) + .text_sm() + .child( + div() + .text_color(cx.theme().text_danger) + .child(message.reason.clone()), + ) + .child( + div() + .line_clamp(1) + .text_ellipsis() + .text_xs() + .overflow_hidden() + .child(message.raw_event.clone()), + ) + .into_any_element() + } else { + div().id(ix).into_any_element() } } } @@ -33,6 +74,10 @@ impl Panel for TrashPanel { fn panel_id(&self) -> SharedString { self.name.clone() } + + fn title(&self, _cx: &App) -> AnyElement { + self.name.clone().into_any_element() + } } impl EventEmitter for TrashPanel {} @@ -45,6 +90,20 @@ impl Focusable for TrashPanel { impl Render for TrashPanel { fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { - div() + v_flex().size_full().relative().child( + v_flex() + .flex_1() + .relative() + .child( + list( + self.list_state.clone(), + cx.processor(move |this, ix, window, cx| { + this.render_list_item(ix, window, cx) + }), + ) + .size_full(), + ) + .child(Scrollbar::vertical(&self.list_state)), + ) } }