feat: add error log panel #25

Merged
reya merged 4 commits from feat/trash into master 2026-03-30 07:56:28 +00:00
2 changed files with 73 additions and 9 deletions
Showing only changes of commit 128f7a1242 - Show all commits

View File

@@ -450,6 +450,11 @@ impl ChatRegistry {
self.trashes.read(cx).len() self.trashes.read(cx).len()
} }
/// Get the trash messages entity.
pub fn trashes(&self) -> Entity<BTreeSet<FailedMessage>> {
self.trashes.clone()
}
/// Get the relays that have seen a given message. /// Get the relays that have seen a given message.
pub fn seen_on(&self, id: &EventId) -> HashSet<RelayUrl> { pub fn seen_on(&self, id: &EventId) -> HashSet<RelayUrl> {
self.seens self.seens

View File

@@ -1,15 +1,13 @@
use chat::ChatRegistry;
use gpui::{ use gpui::{
AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable, 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 theme::ActiveTheme;
use ui::button::{Button, ButtonVariants}; use ui::dock::{Panel, PanelEvent};
use ui::dock::{DockPlacement, Panel, PanelEvent}; use ui::scroll::Scrollbar;
use ui::{Icon, IconName, Sizable, StyledExt, h_flex, v_flex}; use ui::v_flex;
use crate::panels::profile;
use crate::workspace::Workspace;
pub fn init(window: &mut Window, cx: &mut App) -> Entity<TrashPanel> { pub fn init(window: &mut Window, cx: &mut App) -> Entity<TrashPanel> {
cx.new(|cx| TrashPanel::new(window, cx)) cx.new(|cx| TrashPanel::new(window, cx))
@@ -18,13 +16,56 @@ pub fn init(window: &mut Window, cx: &mut App) -> Entity<TrashPanel> {
pub struct TrashPanel { pub struct TrashPanel {
name: SharedString, name: SharedString,
focus_handle: FocusHandle, focus_handle: FocusHandle,
/// List state for messages
list_state: ListState,
} }
impl TrashPanel { impl TrashPanel {
fn new(_window: &mut Window, cx: &mut App) -> Self { 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 { Self {
name: "Trash".into(), name: "Trash".into(),
focus_handle: cx.focus_handle(), focus_handle: cx.focus_handle(),
list_state,
}
}
fn render_list_item(
&mut self,
ix: usize,
_window: &mut Window,
cx: &mut Context<Self>,
) -> 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 { fn panel_id(&self) -> SharedString {
self.name.clone() self.name.clone()
} }
fn title(&self, _cx: &App) -> AnyElement {
self.name.clone().into_any_element()
}
} }
impl EventEmitter<PanelEvent> for TrashPanel {} impl EventEmitter<PanelEvent> for TrashPanel {}
@@ -45,6 +90,20 @@ impl Focusable for TrashPanel {
impl Render for TrashPanel { impl Render for TrashPanel {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement { fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> 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)),
)
} }
} }