feat: add error log panel #25

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

View File

@@ -445,6 +445,11 @@ impl ChatRegistry {
.count() .count()
} }
/// Count the number of trash messages.
pub fn count_trash_messages(&self, cx: &App) -> usize {
self.trashes.read(cx).len()
}
/// 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

@@ -4,3 +4,4 @@ pub mod greeter;
pub mod messaging_relays; pub mod messaging_relays;
pub mod profile; pub mod profile;
pub mod relay_list; pub mod relay_list;
pub mod trash;

View File

@@ -0,0 +1,50 @@
use gpui::{
AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
IntoElement, ParentElement, Render, SharedString, Styled, Window, div, svg,
};
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;
pub fn init(window: &mut Window, cx: &mut App) -> Entity<TrashPanel> {
cx.new(|cx| TrashPanel::new(window, cx))
}
pub struct TrashPanel {
name: SharedString,
focus_handle: FocusHandle,
}
impl TrashPanel {
fn new(_window: &mut Window, cx: &mut App) -> Self {
Self {
name: "Trash".into(),
focus_handle: cx.focus_handle(),
}
}
}
impl Panel for TrashPanel {
fn panel_id(&self) -> SharedString {
self.name.clone()
}
}
impl EventEmitter<PanelEvent> for TrashPanel {}
impl Focusable for TrashPanel {
fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
impl Render for TrashPanel {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
}
}

View File

@@ -9,7 +9,8 @@ use device::{DeviceEvent, DeviceRegistry};
use gpui::prelude::FluentBuilder; use gpui::prelude::FluentBuilder;
use gpui::{ use gpui::{
Action, App, AppContext, Axis, Context, Entity, InteractiveElement, IntoElement, ParentElement, Action, App, AppContext, Axis, Context, Entity, InteractiveElement, IntoElement, ParentElement,
Render, SharedString, Styled, Subscription, Window, div, px, Render, SharedString, StatefulInteractiveElement, Styled, Subscription, Window, div, px,
relative,
}; };
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use person::PersonRegistry; use person::PersonRegistry;
@@ -23,11 +24,11 @@ use ui::button::{Button, ButtonVariants};
use ui::dock::{ClosePanel, DockArea, DockItem, DockPlacement, PanelView}; use ui::dock::{ClosePanel, DockArea, DockItem, DockPlacement, PanelView};
use ui::menu::{DropdownMenu, PopupMenuItem}; use ui::menu::{DropdownMenu, PopupMenuItem};
use ui::notification::{Notification, NotificationKind}; use ui::notification::{Notification, NotificationKind};
use ui::{Disableable, IconName, Root, Sizable, WindowExtension, h_flex, v_flex}; use ui::{Disableable, Icon, IconName, Root, Sizable, WindowExtension, h_flex, v_flex};
use crate::dialogs::restore::RestoreEncryption; use crate::dialogs::restore::RestoreEncryption;
use crate::dialogs::{accounts, settings}; use crate::dialogs::{accounts, settings};
use crate::panels::{backup, contact_list, greeter, messaging_relays, profile, relay_list}; use crate::panels::{backup, contact_list, greeter, messaging_relays, profile, relay_list, trash};
use crate::sidebar; use crate::sidebar;
const PREPARE_MSG: &str = "Coop is preparing a new identity for you. This may take a moment..."; const PREPARE_MSG: &str = "Coop is preparing a new identity for you. This may take a moment...";
@@ -764,13 +765,48 @@ impl Workspace {
let nostr = NostrRegistry::global(cx); let nostr = NostrRegistry::global(cx);
let signer = nostr.read(cx).signer(); let signer = nostr.read(cx).signer();
let trashes = ChatRegistry::global(cx);
let trash_messages = trashes.read(cx).count_trash_messages(cx);
let Some(public_key) = signer.public_key() else { let Some(public_key) = signer.public_key() else {
return div(); return div();
}; };
h_flex() h_flex()
.when(!cx.theme().platform.is_mac(), |this| this.pr_2()) .when(!cx.theme().platform.is_mac(), |this| this.pr_2())
.gap_3() .gap_2()
.when(trash_messages > 0, |this| {
this.child(
h_flex()
.id("trash-messages")
.h_6()
.px_1()
.gap_1()
.rounded(cx.theme().radius)
.hover(|this| this.bg(cx.theme().ghost_element_hover))
.child(
Icon::new(IconName::Warning)
.small()
.text_color(cx.theme().text_danger),
)
.child(
div()
.text_xs()
.line_height(relative(1.))
.child(format!("{trash_messages}")),
)
.on_click(move |_ev, window, cx| {
cx.stop_propagation();
// Add the trash panel to the center workspace
Self::add_panel(
trash::init(window, cx),
DockPlacement::Center,
window,
cx,
);
}),
)
})
.child( .child(
Button::new("key") Button::new("key")
.icon(IconName::UserKey) .icon(IconName::UserKey)