wip: refactor
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
use coop_ui::{
|
||||
use gpui::*;
|
||||
use nostr_sdk::prelude::*;
|
||||
use prelude::FluentBuilder;
|
||||
use ui::{
|
||||
button::{Button, ButtonVariants},
|
||||
popup_menu::PopupMenuExt,
|
||||
Icon, IconName, Sizable,
|
||||
};
|
||||
use gpui::*;
|
||||
use nostr_sdk::prelude::*;
|
||||
use prelude::FluentBuilder;
|
||||
|
||||
use crate::{
|
||||
constants::IMAGE_SERVICE,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use coop_ui::{
|
||||
dock::{DockArea, DockItem, DockPlacement},
|
||||
theme::Theme,
|
||||
Root, TitleBar,
|
||||
};
|
||||
use gpui::*;
|
||||
use prelude::FluentBuilder;
|
||||
use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
use ui::{
|
||||
dock::{DockArea, DockItem, DockPlacement},
|
||||
theme::Theme,
|
||||
Root, TitleBar,
|
||||
};
|
||||
|
||||
use super::{
|
||||
account::Account, chat::ChatPanel, contact::ContactPanel, onboarding::Onboarding,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use coop_ui::{theme::ActiveTheme, StyledExt};
|
||||
use gpui::*;
|
||||
use nostr_sdk::prelude::*;
|
||||
use prelude::FluentBuilder;
|
||||
use ui::{theme::ActiveTheme, StyledExt};
|
||||
|
||||
use crate::{
|
||||
constants::IMAGE_SERVICE,
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use coop_ui::{
|
||||
use gpui::*;
|
||||
use nostr_sdk::prelude::*;
|
||||
use room::RoomPanel;
|
||||
use ui::{
|
||||
button::Button,
|
||||
dock::{Panel, PanelEvent, PanelState},
|
||||
popup_menu::PopupMenu,
|
||||
};
|
||||
use gpui::*;
|
||||
use nostr_sdk::prelude::*;
|
||||
use room::RoomPanel;
|
||||
|
||||
use crate::states::chat::Room;
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use coop_ui::{
|
||||
use gpui::*;
|
||||
use itertools::Itertools;
|
||||
use nostr_sdk::prelude::*;
|
||||
use std::sync::Arc;
|
||||
use ui::{
|
||||
button::{Button, ButtonVariants},
|
||||
input::{InputEvent, TextInput},
|
||||
theme::ActiveTheme,
|
||||
v_flex, Icon, IconName,
|
||||
};
|
||||
use gpui::*;
|
||||
use itertools::Itertools;
|
||||
use nostr_sdk::prelude::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::message::RoomMessage;
|
||||
use crate::{
|
||||
@@ -43,7 +43,7 @@ impl RoomPanel {
|
||||
let input = cx.new_view(|cx| {
|
||||
TextInput::new(cx)
|
||||
.appearance(false)
|
||||
.text_size(coop_ui::Size::Small)
|
||||
.text_size(ui::Size::Small)
|
||||
.placeholder("Message...")
|
||||
.cleanable()
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use coop_ui::StyledExt;
|
||||
use gpui::*;
|
||||
use nostr_sdk::prelude::*;
|
||||
use prelude::FluentBuilder;
|
||||
use ui::theme::ActiveTheme;
|
||||
|
||||
use crate::{
|
||||
constants::IMAGE_SERVICE,
|
||||
@@ -64,7 +64,7 @@ impl ContactListItem {
|
||||
impl Render for ContactListItem {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let fallback = show_npub(self.public_key, 16);
|
||||
let mut content = div();
|
||||
let mut content = div().h_10().text_sm();
|
||||
|
||||
if let Some(metadata) = self.metadata.read(cx).as_ref() {
|
||||
content = content
|
||||
@@ -73,15 +73,14 @@ impl Render for ContactListItem {
|
||||
.gap_2()
|
||||
.map(|this| {
|
||||
if let Some(picture) = metadata.picture.clone() {
|
||||
this.flex_shrink_0().child(
|
||||
this.child(
|
||||
img(format!("{}/?url={}&w=72&h=72&n=-1", IMAGE_SERVICE, picture))
|
||||
.size_6()
|
||||
.size_8()
|
||||
.rounded_full()
|
||||
.object_fit(ObjectFit::Cover),
|
||||
)
|
||||
} else {
|
||||
this.flex_shrink_0()
|
||||
.child(img("brand/avatar.png").size_6().rounded_full())
|
||||
this.child(img("brand/avatar.png").size_8().rounded_full())
|
||||
}
|
||||
})
|
||||
.map(|this| {
|
||||
@@ -96,20 +95,18 @@ impl Render for ContactListItem {
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_2()
|
||||
.child(
|
||||
img("brand/avatar.png")
|
||||
.flex_shrink_0()
|
||||
.size_6()
|
||||
.rounded_full(),
|
||||
)
|
||||
.child(img("brand/avatar.png").size_8().rounded_full())
|
||||
.child(fallback)
|
||||
}
|
||||
|
||||
div()
|
||||
.scrollable(
|
||||
cx.view().entity_id(),
|
||||
coop_ui::scroll::ScrollbarAxis::Vertical,
|
||||
)
|
||||
.w_full()
|
||||
.px_2()
|
||||
.rounded_md()
|
||||
.hover(|this| {
|
||||
this.bg(cx.theme().muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
})
|
||||
.child(content)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
use gpui::*;
|
||||
use prelude::FluentBuilder;
|
||||
use std::time::Duration;
|
||||
|
||||
use super::item::ContactListItem;
|
||||
use crate::get_client;
|
||||
|
||||
pub struct ContactList {
|
||||
contacts: Model<Option<Vec<View<ContactListItem>>>>,
|
||||
}
|
||||
|
||||
impl ContactList {
|
||||
pub fn new(cx: &mut ViewContext<'_, Self>) -> Self {
|
||||
let contacts = cx.new_model(|_| None);
|
||||
let async_contacts = contacts.clone();
|
||||
|
||||
let mut async_cx = cx.to_async();
|
||||
|
||||
cx.foreground_executor()
|
||||
.spawn({
|
||||
let client = get_client();
|
||||
|
||||
async move {
|
||||
if let Ok(contacts) = async_cx
|
||||
.background_executor()
|
||||
.spawn(async move { client.get_contact_list(Duration::from_secs(3)).await })
|
||||
.await
|
||||
{
|
||||
let views: Vec<View<ContactListItem>> = contacts
|
||||
.into_iter()
|
||||
.map(|contact| {
|
||||
async_cx
|
||||
.new_view(|cx| ContactListItem::new(contact.public_key, cx))
|
||||
.unwrap()
|
||||
})
|
||||
.collect();
|
||||
|
||||
_ = async_cx.update_model(&async_contacts, |model, cx| {
|
||||
*model = Some(views);
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
Self { contacts }
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for ContactList {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
div().when_some(self.contacts.read(cx).as_ref(), |this, contacts| {
|
||||
this.children(contacts.clone())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,19 @@
|
||||
use coop_ui::{
|
||||
use std::time::Duration;
|
||||
|
||||
use gpui::*;
|
||||
use item::ContactListItem;
|
||||
use prelude::FluentBuilder;
|
||||
use ui::{
|
||||
button::Button,
|
||||
dock::{Panel, PanelEvent, PanelState},
|
||||
popup_menu::PopupMenu,
|
||||
scroll::ScrollbarAxis,
|
||||
v_flex, StyledExt,
|
||||
};
|
||||
use gpui::*;
|
||||
use list::ContactList;
|
||||
|
||||
use crate::get_client;
|
||||
|
||||
mod item;
|
||||
mod list;
|
||||
|
||||
pub struct ContactPanel {
|
||||
name: SharedString,
|
||||
@@ -15,7 +21,8 @@ pub struct ContactPanel {
|
||||
zoomable: bool,
|
||||
focus_handle: FocusHandle,
|
||||
// Contacts
|
||||
list: View<ContactList>,
|
||||
view_id: EntityId,
|
||||
contacts: Model<Option<Vec<View<ContactListItem>>>>,
|
||||
}
|
||||
|
||||
impl ContactPanel {
|
||||
@@ -24,14 +31,46 @@ impl ContactPanel {
|
||||
}
|
||||
|
||||
fn view(cx: &mut ViewContext<Self>) -> Self {
|
||||
let list = cx.new_view(ContactList::new);
|
||||
let contacts = cx.new_model(|_| None);
|
||||
let async_contacts = contacts.clone();
|
||||
|
||||
let mut async_cx = cx.to_async();
|
||||
|
||||
cx.foreground_executor()
|
||||
.spawn({
|
||||
let client = get_client();
|
||||
|
||||
async move {
|
||||
if let Ok(contacts) = async_cx
|
||||
.background_executor()
|
||||
.spawn(async move { client.get_contact_list(Duration::from_secs(3)).await })
|
||||
.await
|
||||
{
|
||||
let views: Vec<View<ContactListItem>> = contacts
|
||||
.into_iter()
|
||||
.map(|contact| {
|
||||
async_cx
|
||||
.new_view(|cx| ContactListItem::new(contact.public_key, cx))
|
||||
.unwrap()
|
||||
})
|
||||
.collect();
|
||||
|
||||
_ = async_cx.update_model(&async_contacts, |model, cx| {
|
||||
*model = Some(views);
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
Self {
|
||||
name: "Contacts".into(),
|
||||
closeable: true,
|
||||
zoomable: true,
|
||||
focus_handle: cx.focus_handle(),
|
||||
list,
|
||||
view_id: cx.entity_id(),
|
||||
contacts,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,7 +114,14 @@ impl FocusableView for ContactPanel {
|
||||
}
|
||||
|
||||
impl Render for ContactPanel {
|
||||
fn render(&mut self, _cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
|
||||
div().size_full().child(self.list.clone())
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.scrollable(self.view_id, ScrollbarAxis::Vertical)
|
||||
.w_full()
|
||||
.gap_1()
|
||||
.p_2()
|
||||
.when_some(self.contacts.read(cx).as_ref(), |this, contacts| {
|
||||
this.children(contacts.clone())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use coop_ui::{theme::ActiveTheme, StyledExt};
|
||||
use gpui::*;
|
||||
use nostr_sdk::prelude::*;
|
||||
use prelude::FluentBuilder;
|
||||
use std::sync::Arc;
|
||||
use ui::{theme::ActiveTheme, StyledExt};
|
||||
|
||||
use crate::{
|
||||
constants::IMAGE_SERVICE,
|
||||
@@ -12,23 +12,18 @@ use crate::{
|
||||
views::app::{AddPanel, PanelKind},
|
||||
};
|
||||
|
||||
pub struct InboxItem {
|
||||
pub struct InboxListItem {
|
||||
id: SharedString,
|
||||
event: Event,
|
||||
metadata: Model<Option<Metadata>>,
|
||||
}
|
||||
|
||||
impl InboxItem {
|
||||
impl InboxListItem {
|
||||
pub fn new(event: Event, cx: &mut ViewContext<'_, Self>) -> Self {
|
||||
let pubkeys: Vec<PublicKey> = event.tags.public_keys().copied().collect();
|
||||
let id = get_room_id(&event.pubkey, &pubkeys).into();
|
||||
let metadata = cx.new_model(|_| None);
|
||||
|
||||
drop(pubkeys);
|
||||
|
||||
// Request metadata
|
||||
_ = cx.global::<SignalRegistry>().tx.send(event.pubkey);
|
||||
|
||||
// Reload when received metadata
|
||||
cx.observe_global::<MetadataRegistry>(|chat, cx| {
|
||||
chat.load_metadata(cx);
|
||||
@@ -42,6 +37,10 @@ impl InboxItem {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn request_metadata(&mut self, cx: &mut ViewContext<Self>) {
|
||||
_ = cx.global::<SignalRegistry>().tx.send(self.event.pubkey);
|
||||
}
|
||||
|
||||
pub fn load_metadata(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let public_key = self.event.pubkey;
|
||||
let async_metadata = self.metadata.clone();
|
||||
@@ -74,12 +73,12 @@ impl InboxItem {
|
||||
|
||||
cx.dispatch_action(Box::new(AddPanel {
|
||||
panel: PanelKind::Room(room),
|
||||
position: coop_ui::dock::DockPlacement::Center,
|
||||
position: ui::dock::DockPlacement::Center,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for InboxItem {
|
||||
impl Render for InboxListItem {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let ago = ago(self.event.created_at.as_u64());
|
||||
let fallback_name = show_npub(self.event.pubkey, 16);
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
use coop_ui::{
|
||||
skeleton::Skeleton, theme::ActiveTheme, v_flex, Collapsible, Icon, IconName, StyledExt,
|
||||
};
|
||||
use gpui::*;
|
||||
use item::InboxItem;
|
||||
use itertools::Itertools;
|
||||
use nostr_sdk::prelude::*;
|
||||
use prelude::FluentBuilder;
|
||||
use std::cmp::Reverse;
|
||||
use ui::{skeleton::Skeleton, theme::ActiveTheme, v_flex, Collapsible, Icon, IconName, StyledExt};
|
||||
|
||||
use super::inbox::item::InboxListItem;
|
||||
use crate::{get_client, states::chat::ChatRegistry, utils::get_room_id};
|
||||
|
||||
pub mod item;
|
||||
|
||||
pub struct Inbox {
|
||||
label: SharedString,
|
||||
items: Model<Option<Vec<View<InboxItem>>>>,
|
||||
items: Model<Option<Vec<View<InboxListItem>>>>,
|
||||
is_loading: bool,
|
||||
is_collapsed: bool,
|
||||
}
|
||||
@@ -56,7 +54,7 @@ impl Inbox {
|
||||
// Create view for new chats only
|
||||
let new = messages
|
||||
.into_iter()
|
||||
.map(|m| cx.new_view(|cx| InboxItem::new(m.event, cx)))
|
||||
.map(|m| cx.new_view(|cx| InboxListItem::new(m.event, cx)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
cx.update_model(&this.items, |a, b| {
|
||||
@@ -70,8 +68,9 @@ impl Inbox {
|
||||
})
|
||||
.detach();
|
||||
|
||||
cx.observe_new_views::<InboxItem>(|chat, cx| {
|
||||
chat.load_metadata(cx);
|
||||
cx.observe_new_views::<InboxListItem>(|item, cx| {
|
||||
item.request_metadata(cx);
|
||||
item.load_metadata(cx);
|
||||
})
|
||||
.detach();
|
||||
|
||||
@@ -124,17 +123,15 @@ impl Inbox {
|
||||
})
|
||||
.await;
|
||||
|
||||
let views: Vec<View<InboxItem>> = events
|
||||
let views: Vec<View<InboxListItem>> = events
|
||||
.into_iter()
|
||||
.filter(|ev| {
|
||||
let keys = ev.tags.public_keys().copied().collect::<Vec<_>>();
|
||||
let new_id = get_room_id(&ev.pubkey, &keys);
|
||||
|
||||
drop(keys);
|
||||
|
||||
!current_rooms.iter().any(|id| id == &new_id)
|
||||
})
|
||||
.map(|ev| async_cx.new_view(|cx| InboxItem::new(ev, cx)).unwrap())
|
||||
.map(|ev| async_cx.new_view(|cx| InboxListItem::new(ev, cx)).unwrap())
|
||||
.collect();
|
||||
|
||||
async_cx.update_model(&async_items, |model, cx| {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use async_utility::task::spawn;
|
||||
use coop_ui::{
|
||||
input::{InputEvent, TextInput},
|
||||
label::Label,
|
||||
};
|
||||
use gpui::*;
|
||||
use keyring::Entry;
|
||||
use nostr_sdk::prelude::*;
|
||||
use ui::{
|
||||
input::{InputEvent, TextInput},
|
||||
label::Label,
|
||||
};
|
||||
|
||||
use crate::{constants::KEYRING_SERVICE, get_client, states::account::AccountRegistry};
|
||||
|
||||
@@ -17,7 +17,7 @@ impl Onboarding {
|
||||
pub fn new(cx: &mut ViewContext<'_, Self>) -> Self {
|
||||
let input = cx.new_view(|cx| {
|
||||
let mut input = TextInput::new(cx);
|
||||
input.set_size(coop_ui::Size::Medium, cx);
|
||||
input.set_size(ui::Size::Medium, cx);
|
||||
input
|
||||
});
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use coop_ui::{
|
||||
use gpui::*;
|
||||
use ui::{
|
||||
button::{Button, ButtonVariants},
|
||||
dock::{Panel, PanelEvent, PanelState},
|
||||
popup_menu::PopupMenu,
|
||||
scroll::ScrollbarAxis,
|
||||
v_flex, ContextModal, Icon, IconName, Sizable, StyledExt,
|
||||
};
|
||||
use gpui::*;
|
||||
|
||||
use super::inbox::Inbox;
|
||||
use crate::views::app::{AddPanel, PanelKind};
|
||||
@@ -93,9 +93,8 @@ impl Render for Sidebar {
|
||||
.small()
|
||||
.ghost()
|
||||
.not_centered()
|
||||
.bold()
|
||||
.icon(Icon::new(IconName::Plus))
|
||||
.label("New")
|
||||
.icon(Icon::new(IconName::ComposeFill))
|
||||
.label("New Message")
|
||||
.on_click(|_, cx| {
|
||||
cx.open_modal(move |modal, _| modal.child("TODO"));
|
||||
}),
|
||||
@@ -105,13 +104,12 @@ impl Render for Sidebar {
|
||||
.small()
|
||||
.ghost()
|
||||
.not_centered()
|
||||
.bold()
|
||||
.icon(Icon::new(IconName::Group))
|
||||
.icon(Icon::new(IconName::GroupFill))
|
||||
.label("Contacts")
|
||||
.on_click(|_, cx| {
|
||||
cx.dispatch_action(Box::new(AddPanel {
|
||||
panel: PanelKind::Contact,
|
||||
position: coop_ui::dock::DockPlacement::Center,
|
||||
position: ui::dock::DockPlacement::Center,
|
||||
}))
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use coop_ui::{
|
||||
use gpui::*;
|
||||
use ui::{
|
||||
button::Button,
|
||||
dock::{Panel, PanelEvent, PanelState},
|
||||
popup_menu::PopupMenu,
|
||||
theme::{ActiveTheme, Colorize},
|
||||
StyledExt,
|
||||
};
|
||||
use gpui::*;
|
||||
|
||||
pub struct WelcomePanel {
|
||||
name: SharedString,
|
||||
|
||||
Reference in New Issue
Block a user