use std::collections::BTreeSet; use anyhow::Error; use common::profile::SharedProfile; use global::get_client; use gpui::{ div, img, prelude::FluentBuilder, px, uniform_list, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, Task, Window, }; use itertools::Itertools; use nostr_sdk::prelude::*; use ui::{ button::Button, dock_area::panel::{Panel, PanelEvent}, indicator::Indicator, popup_menu::PopupMenu, theme::{scale::ColorScaleStep, ActiveTheme}, Sizable, }; pub fn init(window: &mut Window, cx: &mut App) -> Entity { Contacts::new(window, cx) } pub struct Contacts { contacts: Option>, // Panel name: SharedString, closable: bool, zoomable: bool, focus_handle: FocusHandle, } impl Contacts { pub fn new(window: &mut Window, cx: &mut App) -> Entity { cx.new(|cx| Self::view(window, cx)) } fn view(_window: &mut Window, cx: &mut Context) -> Self { cx.spawn(async move |this, cx| { let client = get_client(); let task: Task, Error>> = cx.background_spawn(async move { let signer = client.signer().await?; let public_key = signer.get_public_key().await?; let profiles = client.database().contacts(public_key).await?; Ok(profiles) }); if let Ok(contacts) = task.await { cx.update(|cx| { this.update(cx, |this, cx| { this.contacts = Some(contacts.into_iter().collect_vec()); cx.notify(); }) .ok(); }) .ok(); } }) .detach(); Self { contacts: None, name: "Contacts".into(), closable: true, zoomable: true, focus_handle: cx.focus_handle(), } } } impl Panel for Contacts { fn panel_id(&self) -> SharedString { "ContactPanel".into() } fn title(&self, _cx: &App) -> AnyElement { self.name.clone().into_any_element() } fn closable(&self, _cx: &App) -> bool { self.closable } fn zoomable(&self, _cx: &App) -> bool { self.zoomable } fn popup_menu(&self, menu: PopupMenu, _cx: &App) -> PopupMenu { menu.track_focus(&self.focus_handle) } fn toolbar_buttons(&self, _window: &Window, _cx: &App) -> Vec